package org.checkerframework.framework.type.treeannotator;

import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.lang.model.element.AnnotationMirror;
import org.checkerframework.framework.qual.LiteralKind;
import org.checkerframework.framework.qual.QualifierForLiterals;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.GenericAnnotatedTypeFactory;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.framework.type.typeannotator.DefaultForTypeAnnotator;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.BugInCF;
import org.plumelib.util.StringsPlume;

/**
 * Adds annotations to a type based on the contents of a tree. This class applies annotations
 * specified by {@link org.checkerframework.framework.qual.QualifierForLiterals}; it is designed to
 * be added to a {@link ListTreeAnnotator} via {@link
 * GenericAnnotatedTypeFactory#createTreeAnnotator()}
 *
 * <p>{@link LiteralTreeAnnotator} does not traverse trees deeply.
 *
 * @see TreeAnnotator
 */
public class LiteralTreeAnnotator extends TreeAnnotator {

  /* The following three fields are mappings from a particular AST kind,
   * AST Class, or String literal pattern to the set of AnnotationMirrors
   * that should be defaulted.
   * There can be at most one qualifier per qualifier hierarchy.
   * For type systems with single top qualifiers, the sets will always contain
   * at most one element.
   */
  private final Map<Kind, Set<AnnotationMirror>> treeKinds;
  private final Map<Class<?>, Set<AnnotationMirror>> treeClasses;
  private final IdentityHashMap<Pattern, Set<AnnotationMirror>> stringPatterns;

  protected final QualifierHierarchy qualHierarchy;

  /**
   * Map of {@link LiteralKind}s to {@link Tree.Kind}s. This is here and not in LiteralKinds because
   * LiteralKind is in the checker-qual.jar which cannot depend on classes, such as Tree.Kind, that
   * are in the tools.jar
   */
  private static final Map<LiteralKind, Tree.Kind> literalKindToTreeKind =
      new EnumMap<>(LiteralKind.class);

  static {
    literalKindToTreeKind.put(LiteralKind.BOOLEAN, Kind.BOOLEAN_LITERAL);
    literalKindToTreeKind.put(LiteralKind.CHAR, Kind.CHAR_LITERAL);
    literalKindToTreeKind.put(LiteralKind.DOUBLE, Kind.DOUBLE_LITERAL);
    literalKindToTreeKind.put(LiteralKind.FLOAT, Kind.FLOAT_LITERAL);
    literalKindToTreeKind.put(LiteralKind.INT, Kind.INT_LITERAL);
    literalKindToTreeKind.put(LiteralKind.LONG, Kind.LONG_LITERAL);
    literalKindToTreeKind.put(LiteralKind.NULL, Kind.NULL_LITERAL);
    literalKindToTreeKind.put(LiteralKind.STRING, Kind.STRING_LITERAL);
  }

  /** Creates a {@link LiteralTreeAnnotator} for the given {@code atypeFactory}. */
  public LiteralTreeAnnotator(AnnotatedTypeFactory atypeFactory) {
    super(atypeFactory);
    this.treeKinds = new EnumMap<>(Kind.class);
    this.treeClasses = new HashMap<>();
    this.stringPatterns = new IdentityHashMap<>();

    this.qualHierarchy = atypeFactory.getQualifierHierarchy();

    // Get type qualifiers from the checker.
    Set<Class<? extends Annotation>> quals = atypeFactory.getSupportedTypeQualifiers();

    // For each qualifier, read the @QualifierForLiterals annotation and put its contents into maps.
    for (Class<? extends Annotation> qual : quals) {
      QualifierForLiterals forLiterals = qual.getAnnotation(QualifierForLiterals.class);
      if (forLiterals == null) {
        continue;
      }

      AnnotationMirror theQual = AnnotationBuilder.fromClass(atypeFactory.getElementUtils(), qual);
      for (LiteralKind literalKind : forLiterals.value()) {
        addLiteralKind(literalKind, theQual);
      }

      for (String pattern : forLiterals.stringPatterns()) {
        addStringPattern(pattern, theQual);
      }

      if (forLiterals.value().length == 0 && forLiterals.stringPatterns().length == 0) {
        addLiteralKind(LiteralKind.ALL, theQual);
      }
    }
  }

  /**
   * Adds standard qualifiers for literals. Currently sets the null literal to bottom if no other
   * default is set for null literals. Also, see {@link
   * DefaultForTypeAnnotator#addStandardDefaults()}.
   *
   * @return this
   */
  public LiteralTreeAnnotator addStandardLiteralQualifiers() {
    // Set null to bottom if no other qualifier is given.
    if (!treeKinds.containsKey(Kind.NULL_LITERAL)) {
      for (AnnotationMirror bottom : qualHierarchy.getBottomAnnotations()) {
        addLiteralKind(LiteralKind.NULL, bottom);
      }
      return this;
    }
    Set<? extends AnnotationMirror> tops = qualHierarchy.getTopAnnotations();
    Set<AnnotationMirror> defaultForNull = treeKinds.get(Kind.NULL_LITERAL);
    if (tops.size() == defaultForNull.size()) {
      return this;
    }
    for (AnnotationMirror top : tops) {
      if (qualHierarchy.findAnnotationInHierarchy(defaultForNull, top) == null) {
        defaultForNull.add(qualHierarchy.getBottomAnnotation(top));
      }
    }
    return this;
  }

  /**
   * Added a rule for a particular {@link LiteralKind}
   *
   * @param literalKind {@code LiteralKind} that should be defaulted to {@code theQual}
   * @param theQual the {@code AnnotationMirror} that should be applied to the {@code literalKind}
   */
  public void addLiteralKind(LiteralKind literalKind, AnnotationMirror theQual) {
    if (literalKind == LiteralKind.ALL) {
      for (LiteralKind iterLiteralKind : LiteralKind.allLiteralKinds()) {
        addLiteralKind(iterLiteralKind, theQual);
      }
    } else if (literalKind == LiteralKind.PRIMITIVE) {
      for (LiteralKind iterLiteralKind : LiteralKind.primitiveLiteralKinds()) {
        addLiteralKind(iterLiteralKind, theQual);
      }
    } else {
      Tree.Kind treeKind = literalKindToTreeKind.get(literalKind);
      if (treeKind != null) {
        addTreeKind(treeKind, theQual);
      } else {
        throw new BugInCF("LiteralKind " + literalKind + " is not mapped to a Tree.Kind.");
      }
    }
  }

  /**
   * Added a rule for a particular {@link com.sun.source.tree.Tree.Kind}
   *
   * @param treeKind {@code Tree.Kind} that should be implicited to {@code theQual}
   * @param theQual the {@code AnnotationMirror} that should be applied to the {@code treeKind}
   */
  private void addTreeKind(Kind treeKind, AnnotationMirror theQual) {
    boolean res = qualHierarchy.updateMappingToMutableSet(treeKinds, treeKind, theQual);
    if (!res) {
      throw new BugInCF(
          "LiteralTreeAnnotator: tried to add mapping %s=%s to %s", treeKind, theQual, treeKinds);
    }
  }

  /**
   * Added a rule for all String literals that match the given pattern.
   *
   * @param pattern pattern to match Strings against
   * @param theQual {@code AnnotationMirror} to apply to Strings that match the pattern
   */
  public void addStringPattern(String pattern, AnnotationMirror theQual) {
    boolean res =
        qualHierarchy.updateMappingToMutableSet(stringPatterns, Pattern.compile(pattern), theQual);
    if (!res) {
      throw new BugInCF(
          "LiteralTreeAnnotator: invalid update of stringPatterns "
              + stringPatterns
              + " at "
              + pattern
              + " with "
              + theQual);
    }
  }

  @Override
  public Void defaultAction(Tree tree, AnnotatedTypeMirror type) {
    if (tree == null || type == null) {
      return null;
    }

    // If this tree's kind is in treeKinds, annotate the type.

    // If this tree's class or any of its interfaces are in treeClasses, annotate the type, and
    // if it was an interface add a mapping for it to treeClasses.
    if (treeKinds.containsKey(tree.getKind())) {
      Set<AnnotationMirror> fnd = treeKinds.get(tree.getKind());
      type.addMissingAnnotations(fnd);
    } else if (!treeClasses.isEmpty()) {
      Class<? extends Tree> t = tree.getClass();
      if (treeClasses.containsKey(t)) {
        Set<AnnotationMirror> fnd = treeClasses.get(t);
        type.addMissingAnnotations(fnd);
      }
      for (Class<?> c : t.getInterfaces()) {
        if (treeClasses.containsKey(c)) {
          Set<AnnotationMirror> fnd = treeClasses.get(c);
          type.addMissingAnnotations(fnd);
          treeClasses.put(t, treeClasses.get(c));
        }
      }
    }
    return null;
  }

  /** Go through the string patterns and add the greatest lower bound of all matching patterns. */
  @Override
  public Void visitLiteral(LiteralTree tree, AnnotatedTypeMirror type) {
    if (!stringPatterns.isEmpty() && tree.getKind() == Kind.STRING_LITERAL) {
      List<Set<? extends AnnotationMirror>> matches = new ArrayList<>();
      List<Set<? extends AnnotationMirror>> nonMatches = new ArrayList<>();

      String string = (String) tree.getValue();
      for (Pattern pattern : stringPatterns.keySet()) {
        Set<AnnotationMirror> sam = stringPatterns.get(pattern);
        if (pattern.matcher(string).matches()) {
          matches.add(sam);
        } else {
          nonMatches.add(sam);
        }
      }
      if (!matches.isEmpty()) {
        Set<? extends AnnotationMirror> res = matches.get(0);
        for (Set<? extends AnnotationMirror> sam : matches) {
          res = qualHierarchy.greatestLowerBounds(res, sam);
        }
        // Verify that res is not a subtype of any type in nonMatches
        for (Set<? extends AnnotationMirror> sam : nonMatches) {
          if (qualHierarchy.isSubtype(res, sam)) {
            String matchesOnePerLine = "";
            for (Set<? extends AnnotationMirror> match : matches) {
              matchesOnePerLine += System.lineSeparator() + "     " + match;
            }
            throw new BugInCF(
                StringsPlume.joinLines(
                    "Bug in @QualifierForLiterals(stringpatterns=...) in type hierarchy"
                        + " definition:",
                    " the glb of `matches` for \"" + string + "\" is " + res,
                    " which is a subtype of " + sam,
                    " whose pattern does not match \"" + string + "\".",
                    "  matches = " + matchesOnePerLine,
                    "  nonMatches = " + nonMatches));
          }
        }
        type.addAnnotations(res);
      }
    }
    return super.visitLiteral(tree, type);
  }
}
