package org.checkerframework.checker.regex;

import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.Tree;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.regex.Pattern;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.util.Elements;
import org.checkerframework.checker.regex.qual.PartialRegex;
import org.checkerframework.checker.regex.qual.PolyRegex;
import org.checkerframework.checker.regex.qual.Regex;
import org.checkerframework.checker.regex.qual.RegexBottom;
import org.checkerframework.checker.regex.qual.UnknownRegex;
import org.checkerframework.checker.regex.util.RegexUtil;
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.framework.flow.CFAbstractAnalysis;
import org.checkerframework.framework.flow.CFAnalysis;
import org.checkerframework.framework.flow.CFStore;
import org.checkerframework.framework.flow.CFTransfer;
import org.checkerframework.framework.flow.CFValue;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import org.checkerframework.framework.type.MostlyNoElementQualifierHierarchy;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.LiteralTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.PropagationTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
import org.checkerframework.framework.util.QualifierKind;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.TreeUtils;

/**
 * Adds {@link Regex} to the type of tree, in the following cases:
 *
 * <ol>
 *   <li value="1">a {@code String} or {@code char} literal that is a valid regular expression
 *   <li value="2">concatenation of two valid regular expression values (either {@code String} or
 *       {@code char}) or two partial regular expression values that make a valid regular expression
 *       when concatenated.
 *   <li value="3">for calls to Pattern.compile, change the group count value of the return type to
 *       be the same as the parameter. For calls to the asRegex methods of the classes in
 *       asRegexClasses, the returned {@code @Regex String} gets the same group count as the second
 *       argument to the call to asRegex.
 *       <!--<li value="4">initialization of a char array that when converted to a String
 * is a valid regular expression.</li>-->
 * </ol>
 *
 * Provides a basic analysis of concatenation of partial regular expressions to determine if a valid
 * regular expression is produced by concatenating non-regular expression Strings. Do do this,
 * {@link PartialRegex} is added to the type of tree in the following cases:
 *
 * <ol>
 *   <li value="1">a String literal that is not a valid regular expression.
 *   <li value="2">concatenation of two partial regex Strings that doesn't result in a regex String
 *       or a partial regex and regex String.
 * </ol>
 *
 * Also, adds {@link PolyRegex} to the type of String/char concatenation of a Regex and a PolyRegex
 * or two PolyRegexs.
 */
public class RegexAnnotatedTypeFactory extends BaseAnnotatedTypeFactory {

  /** The @{@link Regex} annotation. */
  protected final AnnotationMirror REGEX = AnnotationBuilder.fromClass(elements, Regex.class);
  /** The @{@link RegexBottom} annotation. */
  protected final AnnotationMirror REGEXBOTTOM =
      AnnotationBuilder.fromClass(elements, RegexBottom.class);
  /** The @{@link PartialRegex} annotation. */
  protected final AnnotationMirror PARTIALREGEX =
      AnnotationBuilder.fromClass(elements, PartialRegex.class);
  /** The @{@link PolyRegex} annotation. */
  protected final AnnotationMirror POLYREGEX =
      AnnotationBuilder.fromClass(elements, PolyRegex.class);
  /** The @{@link UnknownRegex} annotation. */
  protected final AnnotationMirror UNKNOWNREGEX =
      AnnotationBuilder.fromClass(elements, UnknownRegex.class);

  /** The method that returns the value element of a {@code @Regex} annotation. */
  protected final ExecutableElement regexValueElement =
      TreeUtils.getMethod(
          "org.checkerframework.checker.regex.qual.Regex", "value", 0, processingEnv);

  /**
   * The value method of the PartialRegex qualifier.
   *
   * @see org.checkerframework.checker.regex.qual.PartialRegex
   */
  private final ExecutableElement partialRegexValueElement =
      TreeUtils.getMethod(PartialRegex.class, "value", 0, processingEnv);

  /**
   * The Pattern.compile method.
   *
   * @see java.util.regex.Pattern#compile(String)
   */
  private final ExecutableElement patternCompile =
      TreeUtils.getMethod("java.util.regex.Pattern", "compile", 1, processingEnv);

  /**
   * Create a new RegexAnnotatedTypeFactory.
   *
   * @param checker the checker
   */
  public RegexAnnotatedTypeFactory(BaseTypeChecker checker) {
    super(checker);

    this.postInit();
  }

  @Override
  protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers() {
    return getBundledTypeQualifiers(
        Regex.class, PartialRegex.class,
        RegexBottom.class, UnknownRegex.class);
  }

  @Override
  public CFTransfer createFlowTransferFunction(
      CFAbstractAnalysis<CFValue, CFStore, CFTransfer> analysis) {
    return new RegexTransfer((CFAnalysis) analysis);
  }

  /** Returns a new Regex annotation with the given group count. */
  /*package-scope*/ AnnotationMirror createRegexAnnotation(int groupCount) {
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, Regex.class);
    if (groupCount > 0) {
      builder.setValue("value", groupCount);
    }
    return builder.build();
  }

  @Override
  protected QualifierHierarchy createQualifierHierarchy() {
    return new RegexQualifierHierarchy(this.getSupportedTypeQualifiers(), elements);
  }

  /**
   * A custom qualifier hierarchy for the Regex Checker. This makes a regex annotation a subtype of
   * all regex annotations with lower group count values. For example, {@code @Regex(3)} is a
   * subtype of {@code @Regex(1)}. All regex annotations are subtypes of {@code @Regex}, which has a
   * default value of 0.
   */
  private final class RegexQualifierHierarchy extends MostlyNoElementQualifierHierarchy {

    /** Qualifier kind for the @{@link Regex} annotation. */
    private final QualifierKind REGEX_KIND;
    /** Qualifier kind for the @{@link PartialRegex} annotation. */
    private final QualifierKind PARTIALREGEX_KIND;
    /**
     * Creates a RegexQualifierHierarchy from the given classes.
     *
     * @param qualifierClasses classes of annotations that are the qualifiers for this hierarchy
     * @param elements element utils
     */
    private RegexQualifierHierarchy(
        Collection<Class<? extends Annotation>> qualifierClasses, Elements elements) {
      super(qualifierClasses, elements);
      REGEX_KIND = getQualifierKind(REGEX);
      PARTIALREGEX_KIND = getQualifierKind(PARTIALREGEX);
    }

    @Override
    protected boolean isSubtypeWithElements(
        AnnotationMirror subAnno,
        QualifierKind subKind,
        AnnotationMirror superAnno,
        QualifierKind superKind) {
      if (subKind == REGEX_KIND && superKind == REGEX_KIND) {
        int rhsValue = getRegexValue(subAnno);
        int lhsValue = getRegexValue(superAnno);
        return lhsValue <= rhsValue;
      } else if (subKind == PARTIALREGEX_KIND && superKind == PARTIALREGEX_KIND) {
        return AnnotationUtils.areSame(subAnno, superAnno);
      }
      throw new BugInCF("Unexpected qualifiers: %s %s", subAnno, superAnno);
    }

    @Override
    protected AnnotationMirror leastUpperBoundWithElements(
        AnnotationMirror a1,
        QualifierKind qualifierKind1,
        AnnotationMirror a2,
        QualifierKind qualifierKind2,
        QualifierKind lubKind) {
      if (qualifierKind1 == REGEX_KIND && qualifierKind2 == REGEX_KIND) {
        int value1 = getRegexValue(a1);
        int value2 = getRegexValue(a2);
        if (value1 < value2) {
          return a1;
        } else {
          return a2;
        }
      } else if (qualifierKind1 == PARTIALREGEX_KIND && qualifierKind2 == PARTIALREGEX_KIND) {
        if (AnnotationUtils.areSame(a1, a2)) {
          return a1;
        } else {
          return UNKNOWNREGEX;
        }
      } else if (qualifierKind1 == PARTIALREGEX_KIND || qualifierKind1 == REGEX_KIND) {
        return a1;
      } else if (qualifierKind2 == PARTIALREGEX_KIND || qualifierKind2 == REGEX_KIND) {
        return a2;
      }
      throw new BugInCF("Unexpected qualifiers: %s %s", a1, a2);
    }

    @Override
    protected AnnotationMirror greatestLowerBoundWithElements(
        AnnotationMirror a1,
        QualifierKind qualifierKind1,
        AnnotationMirror a2,
        QualifierKind qualifierKind2,
        QualifierKind glbKind) {
      if (qualifierKind1 == REGEX_KIND && qualifierKind2 == REGEX_KIND) {
        int value1 = getRegexValue(a1);
        int value2 = getRegexValue(a2);
        if (value1 > value2) {
          return a1;
        } else {
          return a2;
        }
      } else if (qualifierKind1 == PARTIALREGEX_KIND && qualifierKind2 == PARTIALREGEX_KIND) {
        if (AnnotationUtils.areSame(a1, a2)) {
          return a1;
        } else {
          return REGEXBOTTOM;
        }
      } else if (qualifierKind1 == PARTIALREGEX_KIND || qualifierKind1 == REGEX_KIND) {
        return a1;
      } else if (qualifierKind2 == PARTIALREGEX_KIND || qualifierKind2 == REGEX_KIND) {
        return a2;
      }
      throw new BugInCF("Unexpected qualifiers: %s %s", a1, a2);
    }

    /**
     * Gets the value out of a regex annotation.
     *
     * @param anno a @Regex annotation
     * @return the {@code value} element of the annotation
     */
    private int getRegexValue(AnnotationMirror anno) {
      return AnnotationUtils.getElementValue(anno, regexValueElement, Integer.class, 0);
    }
  }

  /**
   * Returns the group count value of the given annotation or 0 if there's a problem getting the
   * group count value.
   *
   * @param anno a @Regex annotation
   * @return the {@code value} element of the annotation
   */
  public int getGroupCount(AnnotationMirror anno) {
    if (anno == null) {
      return 0;
    }
    return AnnotationUtils.getElementValue(anno, regexValueElement, Integer.class, 0);
  }

  /** Returns the number of groups in the given regex String. */
  public static int getGroupCount(@Regex String regexp) {
    return Pattern.compile(regexp).matcher("").groupCount();
  }

  @Override
  public Set<AnnotationMirror> getWidenedAnnotations(
      Set<AnnotationMirror> annos, TypeKind typeKind, TypeKind widenedTypeKind) {
    return Collections.singleton(UNKNOWNREGEX);
  }

  @Override
  public TreeAnnotator createTreeAnnotator() {
    // Don't call super.createTreeAnnotator because the PropagationTreeAnnotator types binary
    // expressions as lub.
    return new ListTreeAnnotator(
        new LiteralTreeAnnotator(this).addStandardLiteralQualifiers(),
        new RegexTreeAnnotator(this),
        new RegexPropagationTreeAnnotator(this));
  }

  private static class RegexPropagationTreeAnnotator extends PropagationTreeAnnotator {

    public RegexPropagationTreeAnnotator(AnnotatedTypeFactory atypeFactory) {
      super(atypeFactory);
    }

    @Override
    public Void visitBinary(BinaryTree node, AnnotatedTypeMirror type) {
      // Don't call super method which will try to create a LUB
      // Even when it is not yet valid: i.e. between a @PolyRegex and a @Regex
      return null;
    }
  }

  private class RegexTreeAnnotator extends TreeAnnotator {

    public RegexTreeAnnotator(AnnotatedTypeFactory atypeFactory) {
      super(atypeFactory);
    }

    /**
     * Case 1: valid regular expression String or char literal. Adds PartialRegex annotation to
     * String literals that are not valid regular expressions.
     */
    @Override
    public Void visitLiteral(LiteralTree tree, AnnotatedTypeMirror type) {
      if (!type.isAnnotatedInHierarchy(REGEX)) {
        String regex = null;
        if (tree.getKind() == Tree.Kind.STRING_LITERAL) {
          regex = (String) tree.getValue();
        } else if (tree.getKind() == Tree.Kind.CHAR_LITERAL) {
          regex = Character.toString((Character) tree.getValue());
        }
        if (regex != null) {
          if (RegexUtil.isRegex(regex)) {
            int groupCount = getGroupCount(regex);
            type.addAnnotation(createRegexAnnotation(groupCount));
          } else {
            type.addAnnotation(createPartialRegexAnnotation(regex));
          }
        }
      }
      return super.visitLiteral(tree, type);
    }

    /**
     * Case 2: concatenation of Regex or PolyRegex String/char literals. Also handles concatenation
     * of partial regular expressions.
     */
    @Override
    public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) {
      if (!type.isAnnotatedInHierarchy(REGEX) && TreeUtils.isStringConcatenation(tree)) {
        AnnotatedTypeMirror lExpr = getAnnotatedType(tree.getLeftOperand());
        AnnotatedTypeMirror rExpr = getAnnotatedType(tree.getRightOperand());

        Integer lGroupCount = getMinimumRegexCount(lExpr);
        Integer rGroupCount = getMinimumRegexCount(rExpr);
        boolean lExprRE = lGroupCount != null;
        boolean rExprRE = rGroupCount != null;
        boolean lExprPart = lExpr.hasAnnotation(PartialRegex.class);
        boolean rExprPart = rExpr.hasAnnotation(PartialRegex.class);
        boolean lExprPoly = lExpr.hasAnnotation(PolyRegex.class);
        boolean rExprPoly = rExpr.hasAnnotation(PolyRegex.class);

        if (lExprRE && rExprRE) {
          // Remove current @Regex annotation...
          type.removeAnnotationInHierarchy(REGEX);
          // ...and add a new one with the correct group count value.
          type.addAnnotation(createRegexAnnotation(lGroupCount + rGroupCount));
        } else if ((lExprPoly && rExprPoly) || (lExprPoly && rExprRE) || (lExprRE && rExprPoly)) {
          type.addAnnotation(PolyRegex.class);
        } else if (lExprPart && rExprPart) {
          String lRegex = getPartialRegexValue(lExpr);
          String rRegex = getPartialRegexValue(rExpr);
          String concat = lRegex + rRegex;
          if (RegexUtil.isRegex(concat)) {
            int groupCount = getGroupCount(concat);
            type.addAnnotation(createRegexAnnotation(groupCount));
          } else {
            type.addAnnotation(createPartialRegexAnnotation(concat));
          }
        } else if (lExprRE && rExprPart) {
          String rRegex = getPartialRegexValue(rExpr);
          String concat = "e" + rRegex;
          type.addAnnotation(createPartialRegexAnnotation(concat));
        } else if (lExprPart && rExprRE) {
          String lRegex = getPartialRegexValue(lExpr);
          String concat = lRegex + "e";
          type.addAnnotation(createPartialRegexAnnotation(concat));
        }
      }
      return null; // super.visitBinary(tree, type);
    }

    /** Case 2: Also handle compound String concatenation. */
    @Override
    public Void visitCompoundAssignment(CompoundAssignmentTree node, AnnotatedTypeMirror type) {
      if (TreeUtils.isStringCompoundConcatenation(node)) {
        AnnotatedTypeMirror rhs = getAnnotatedType(node.getExpression());
        AnnotatedTypeMirror lhs = getAnnotatedType(node.getVariable());

        final Integer lhsRegexCount = getMinimumRegexCount(lhs);
        final Integer rhsRegexCount = getMinimumRegexCount(rhs);

        if (lhsRegexCount != null && rhsRegexCount != null) {
          int lCount = getGroupCount(lhs.getAnnotation(Regex.class));
          int rCount = getGroupCount(rhs.getAnnotation(Regex.class));
          type.removeAnnotationInHierarchy(REGEX);
          type.addAnnotation(createRegexAnnotation(lCount + rCount));
        }
      }
      return null; // super.visitCompoundAssignment(node, type);
    }

    /**
     * Case 3: For a call to Pattern.compile, add an annotation to the return type that has the same
     * group count value as the parameter. For calls to {@code asRegex(String, int)} change the
     * return type to have the same group count as the value of the second argument.
     */
    @Override
    public Void visitMethodInvocation(MethodInvocationTree tree, AnnotatedTypeMirror type) {
      // TODO: Also get this to work with 2 argument Pattern.compile.
      if (TreeUtils.isMethodInvocation(tree, patternCompile, processingEnv)) {
        ExpressionTree arg0 = tree.getArguments().get(0);

        final AnnotatedTypeMirror argType = getAnnotatedType(arg0);
        Integer regexCount = getMinimumRegexCount(argType);
        AnnotationMirror bottomAnno = getAnnotatedType(arg0).getAnnotation(RegexBottom.class);

        if (regexCount != null) {
          // Remove current @Regex annotation...
          // ...and add a new one with the correct group count value.
          type.replaceAnnotation(createRegexAnnotation(regexCount));
        } else if (bottomAnno != null) {
          type.replaceAnnotation(AnnotationBuilder.fromClass(elements, RegexBottom.class));
        }
      }
      return super.visitMethodInvocation(tree, type);
    }

    /** Returns a new PartialRegex annotation with the given partial regular expression. */
    private AnnotationMirror createPartialRegexAnnotation(String partial) {
      AnnotationBuilder builder = new AnnotationBuilder(processingEnv, PartialRegex.class);
      builder.setValue("value", partial);
      return builder.build();
    }

    /**
     * Returns the {@code value} element of a {@code @PartialRegex} annotation, if there is one in
     * {@code type}.
     *
     * @param type a type
     * @return the {@code value} element of a {@code @PartialRegex} annotation, or "" if none
     */
    private String getPartialRegexValue(AnnotatedTypeMirror type) {
      AnnotationMirror partialRegexAnno = type.getAnnotation(PartialRegex.class);
      if (partialRegexAnno == null) {
        return "";
      }
      return AnnotationUtils.getElementValue(
          partialRegexAnno, partialRegexValueElement, String.class, "");
    }

    /**
     * Returns the value of the Regex annotation on the given type or NULL if there is no Regex
     * annotation. If type is a TYPEVAR, WILDCARD, or INTERSECTION type, visit first their primary
     * annotation then visit their upper bounds to get the Regex annotation. The method gets
     * "minimum" regex count because, depending on the bounds of a typevar or wildcard, the actual
     * type may have more than the upper bound's count.
     *
     * @param type type that may carry a Regex annotation
     * @return the Integer value of the Regex annotation (0 if no value exists)
     */
    private Integer getMinimumRegexCount(final AnnotatedTypeMirror type) {
      final AnnotationMirror primaryRegexAnno = type.getAnnotation(Regex.class);
      if (primaryRegexAnno == null) {
        switch (type.getKind()) {
          case TYPEVAR:
            return getMinimumRegexCount(((AnnotatedTypeVariable) type).getUpperBound());

          case WILDCARD:
            return getMinimumRegexCount(((AnnotatedWildcardType) type).getExtendsBound());

          case INTERSECTION:
            Integer maxBound = null;
            for (final AnnotatedTypeMirror bound : ((AnnotatedIntersectionType) type).getBounds()) {
              Integer boundRegexNum = getMinimumRegexCount(bound);
              if (boundRegexNum != null) {
                if (maxBound == null || boundRegexNum > maxBound) {
                  maxBound = boundRegexNum;
                }
              }
            }
            return maxBound;
          default:
            // Nothing to do for other cases.
        }

        return null;
      }

      return getGroupCount(primaryRegexAnno);
    }

    // This won't work correctly until flow sensitivity is supported by the
    // the Regex Checker. For example:
    //
    //  char @Regex [] arr = {'r', 'e'};
    //  arr[0] = '('; // type is still "char @Regex []", but this is no longer correct
    //
    // There are associated tests in tests/regex/Simple.java:testCharArrays
    // that can be uncommented when this is uncommented.
    // /**
    //  * Case 4: a char array that as a String is a valid regular expression.
    //  */
    // @Override
    // public Void visitNewArray(NewArrayTree tree, AnnotatedTypeMirror type) {
    //     boolean isCharArray = ((ArrayType) type.getUnderlyingType())
    //             .getComponentType().getKind() == TypeKind.CHAR;
    //     if (isCharArray && tree.getInitializers() != null) {
    //         List<? extends ExpressionTree> initializers = tree.getInitializers();
    //         StringBuilder charArray = new StringBuilder();
    //         boolean allLiterals = true;
    //         for (int i = 0; allLiterals && i < initializers.size(); i++) {
    //             ExpressionTree e = initializers.get(i);
    //             if (e.getKind() == Tree.Kind.CHAR_LITERAL) {
    //                 charArray.append(((LiteralTree) e).getValue());
    //             } else if (getAnnotatedType(e).hasAnnotation(Regex.class)) {
    //                 // if there's an @Regex char in the array then substitute
    //                 // it with a .
    //                 charArray.append('.');
    //             } else {
    //                 allLiterals = false;
    //             }
    //         }
    //         if (allLiterals && RegexUtil.isRegex(charArray.toString())) {
    //             type.addAnnotation(Regex.class);
    //         }
    //     }
    //     return super.visitNewArray(tree, type);
    // }
  }
}
