package org.checkerframework.common.value;

import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.TypeCastTree;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
import org.checkerframework.checker.formatter.qual.FormatMethod;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.common.basetype.BaseTypeVisitor;
import org.checkerframework.common.value.qual.IntRangeFromGTENegativeOne;
import org.checkerframework.common.value.qual.IntRangeFromNonNegative;
import org.checkerframework.common.value.qual.IntRangeFromPositive;
import org.checkerframework.common.value.qual.StaticallyExecutable;
import org.checkerframework.common.value.util.NumberUtils;
import org.checkerframework.common.value.util.Range;
import org.checkerframework.dataflow.qual.Pure;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.visitor.AnnotatedTypeScanner;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;

/** Visitor for the Constant Value type system. */
public class ValueVisitor extends BaseTypeVisitor<ValueAnnotatedTypeFactory> {

  public ValueVisitor(BaseTypeChecker checker) {
    super(checker);
  }

  /**
   * ValueVisitor overrides this method so that it does not have to check variables annotated with
   * the {@link IntRangeFromPositive} annotation, the {@link IntRangeFromNonNegative} annotation, or
   * the {@link IntRangeFromGTENegativeOne} annotation. This annotation is only introduced by the
   * Index Checker's lower bound annotations. It is safe to defer checking of these values to the
   * Index Checker because this is only introduced for explicitly-written {@code
   * org.checkerframework.checker.index.qual.Positive}, explicitly-written {@code
   * org.checkerframework.checker.index.qual.NonNegative}, and explicitly-written {@code
   * org.checkerframework.checker.index.qual.GTENegativeOne} annotations, which must be checked by
   * the Lower Bound Checker.
   *
   * @param varType the annotated type of the lvalue (usually a variable)
   * @param valueExp the AST node for the rvalue (the new value)
   * @param errorKey the error message key to use if the check fails
   * @param extraArgs arguments to the error message key, before "found" and "expected" types
   */
  @Override
  protected void commonAssignmentCheck(
      AnnotatedTypeMirror varType,
      ExpressionTree valueExp,
      @CompilerMessageKey String errorKey,
      Object... extraArgs) {

    replaceSpecialIntRangeAnnotations(varType);
    super.commonAssignmentCheck(varType, valueExp, errorKey, extraArgs);
  }

  @Override
  @FormatMethod
  protected void commonAssignmentCheck(
      AnnotatedTypeMirror varType,
      AnnotatedTypeMirror valueType,
      Tree valueTree,
      @CompilerMessageKey String errorKey,
      Object... extraArgs) {

    replaceSpecialIntRangeAnnotations(varType);

    if (valueType.getKind() == TypeKind.CHAR
        && valueType.hasAnnotation(getTypeFactory().UNKNOWNVAL)) {
      valueType.addAnnotation(getTypeFactory().createIntRangeAnnotation(Range.CHAR_EVERYTHING));
    }

    super.commonAssignmentCheck(varType, valueType, valueTree, errorKey, extraArgs);
  }

  /**
   * Return types for methods that are annotated with {@code @IntRangeFromX} annotations need to be
   * replaced with {@code @UnknownVal}. See the documentation on {@link
   * #commonAssignmentCheck(AnnotatedTypeMirror, ExpressionTree, String, Object[])
   * commonAssignmentCheck}.
   *
   * <p>A separate override is necessary because checkOverride doesn't actually use the
   * commonAssignmentCheck.
   */
  @Override
  protected boolean checkOverride(
      MethodTree overriderTree,
      AnnotatedTypeMirror.AnnotatedExecutableType overrider,
      AnnotatedTypeMirror.AnnotatedDeclaredType overridingType,
      AnnotatedTypeMirror.AnnotatedExecutableType overridden,
      AnnotatedTypeMirror.AnnotatedDeclaredType overriddenType) {

    replaceSpecialIntRangeAnnotations(overrider);
    replaceSpecialIntRangeAnnotations(overridden);

    return super.checkOverride(
        overriderTree, overrider, overridingType, overridden, overriddenType);
  }

  /**
   * Replaces any {@code IntRangeFromX} annotations with {@code @UnknownVal}. This is used to
   * prevent these annotations from being required on the left hand side of assignments.
   *
   * @param varType an annotated type mirror that may contain IntRangeFromX annotations, which will
   *     be used on the lhs of an assignment or pseudo-assignment
   */
  private void replaceSpecialIntRangeAnnotations(AnnotatedTypeMirror varType) {
    AnnotatedTypeScanner<Void, Void> replaceSpecialIntRangeAnnotations =
        new AnnotatedTypeScanner<Void, Void>() {
          @Override
          protected Void scan(AnnotatedTypeMirror type, Void p) {
            if (type.hasAnnotation(IntRangeFromPositive.class)
                || type.hasAnnotation(IntRangeFromNonNegative.class)
                || type.hasAnnotation(IntRangeFromGTENegativeOne.class)) {
              type.replaceAnnotation(atypeFactory.UNKNOWNVAL);
            }
            return super.scan(type, p);
          }

          @Override
          public Void visitDeclared(AnnotatedDeclaredType type, Void p) {
            // Don't call super so that the type arguments are not visited.
            if (type.getEnclosingType() != null) {
              scan(type.getEnclosingType(), p);
            }

            return null;
          }
        };
    replaceSpecialIntRangeAnnotations.visit(varType);
  }

  @Override
  protected ValueAnnotatedTypeFactory createTypeFactory() {
    return new ValueAnnotatedTypeFactory(checker);
  }

  /**
   * Warns about malformed constant-value annotations.
   *
   * <p>Issues an error if any @IntRange annotation has its 'from' value greater than 'to' value.
   *
   * <p>Issues an error if any constant-value annotation has no arguments.
   *
   * <p>Issues a warning if any constant-value annotation has &gt; MAX_VALUES arguments.
   *
   * <p>Issues a warning if any @ArrayLen/@ArrayLenRange annotations contain a negative array
   * length.
   *
   * <p>Issues a warning if any {@literal @}MatchesRegex annotation contains an invalid regular
   * expression.
   */
  /* Implementation note: the ValueTypeAnnotator replaces such invalid annotations with valid ones.
   * Therefore, the usual validation in #validateType cannot perform this validation.
   * These warnings cannot be issued in the ValueAnnotatedTypeFactory, because the conversions
   * might happen multiple times.
   * On the other hand, not all validations can happen here, because only the annotations are
   * available, not the full types.
   * Therefore, some validation is still done in #validateType below.
   */
  @Override
  public Void visitAnnotation(AnnotationTree node, Void p) {
    List<? extends ExpressionTree> args = node.getArguments();

    if (args.isEmpty()) {
      // Nothing to do if there are no annotation arguments.
      return super.visitAnnotation(node, p);
    }

    AnnotationMirror anno = TreeUtils.annotationFromAnnotationTree(node);
    switch (AnnotationUtils.annotationName(anno)) {
      case ValueAnnotatedTypeFactory.INTRANGE_NAME:
        // If there are 2 arguments, issue an error if from.greater.than.to.
        // If there are fewer than 2 arguments, we needn't worry about this problem because the
        // other argument will be defaulted to Long.MIN_VALUE or Long.MAX_VALUE accordingly.
        if (args.size() == 2) {
          long from = getTypeFactory().getIntRangeFromValue(anno);
          long to = getTypeFactory().getIntRangeToValue(anno);
          if (from > to) {
            checker.reportError(node, "from.greater.than.to");
            return null;
          }
        }
        break;
      case ValueAnnotatedTypeFactory.ARRAYLEN_NAME:
      case ValueAnnotatedTypeFactory.BOOLVAL_NAME:
      case ValueAnnotatedTypeFactory.DOUBLEVAL_NAME:
      case ValueAnnotatedTypeFactory.INTVAL_NAME:
      case ValueAnnotatedTypeFactory.STRINGVAL_NAME:
        @SuppressWarnings("deprecation") // concrete annotation class is not known
        List<Object> values =
            AnnotationUtils.getElementValueArray(anno, "value", Object.class, false);

        if (values.isEmpty()) {
          checker.reportWarning(node, "no.values.given");
          return null;
        } else if (values.size() > ValueAnnotatedTypeFactory.MAX_VALUES) {
          checker.reportWarning(
              node,
              (AnnotationUtils.areSameByName(anno, ValueAnnotatedTypeFactory.INTVAL_NAME)
                  ? "too.many.values.given.int"
                  : "too.many.values.given"),
              ValueAnnotatedTypeFactory.MAX_VALUES);
          return null;
        } else if (AnnotationUtils.areSameByName(anno, ValueAnnotatedTypeFactory.ARRAYLEN_NAME)) {
          List<Integer> arrayLens = getTypeFactory().getArrayLength(anno);
          if (Collections.min(arrayLens) < 0) {
            checker.reportWarning(node, "negative.arraylen", Collections.min(arrayLens));
            return null;
          }
        }
        break;
      case ValueAnnotatedTypeFactory.ARRAYLENRANGE_NAME:
        long from = getTypeFactory().getArrayLenRangeFromValue(anno);
        long to = getTypeFactory().getArrayLenRangeToValue(anno);
        if (from > to) {
          checker.reportError(node, "from.greater.than.to");
          return null;
        } else if (from < 0) {
          checker.reportWarning(node, "negative.arraylen", from);
          return null;
        }
        break;
      case ValueAnnotatedTypeFactory.MATCHES_REGEX_NAME:
        List<String> regexes =
            AnnotationUtils.getElementValueArray(
                anno, atypeFactory.matchesRegexValueElement, String.class);
        for (String regex : regexes) {
          try {
            Pattern.compile(regex);
          } catch (PatternSyntaxException pse) {
            checker.reportWarning(node, "invalid.matches.regex", pse.getMessage());
          }
        }
        break;
      default:
        // Do nothing.
    }

    return super.visitAnnotation(node, p);
  }

  @Override
  public Void visitTypeCast(TypeCastTree node, Void p) {
    if (node.getExpression().getKind() == Kind.NULL_LITERAL) {
      return null;
    }

    AnnotatedTypeMirror castType = atypeFactory.getAnnotatedType(node);
    AnnotationMirror castAnno = castType.getAnnotationInHierarchy(atypeFactory.UNKNOWNVAL);
    AnnotationMirror exprAnno =
        atypeFactory
            .getAnnotatedType(node.getExpression())
            .getAnnotationInHierarchy(atypeFactory.UNKNOWNVAL);

    // It is always legal to cast to an IntRange type that includes all values
    // of the underlying type. Do not warn about such casts.
    // I.e. do not warn if an @IntRange(...) int is casted
    // to a @IntRange(from = Byte.MIN_VALUE, to = Byte.MAX_VALUE byte).
    if (castAnno != null
        && exprAnno != null
        && atypeFactory.isIntRange(castAnno)
        && atypeFactory.isIntRange(exprAnno)) {
      final Range castRange = atypeFactory.getRange(castAnno);
      final TypeKind castTypeKind = castType.getKind();
      if (castTypeKind == TypeKind.BYTE && castRange.isByteEverything()) {
        return p;
      }
      if (castTypeKind == TypeKind.CHAR && castRange.isCharEverything()) {
        return p;
      }
      if (castTypeKind == TypeKind.SHORT && castRange.isShortEverything()) {
        return p;
      }
      if (castTypeKind == TypeKind.INT && castRange.isIntEverything()) {
        return p;
      }
      if (castTypeKind == TypeKind.LONG && castRange.isLongEverything()) {
        return p;
      }
      if (Range.ignoreOverflow) {
        // Range.ignoreOverflow is only set if this checker is ignoring overflow.
        // In that case, do not warn if the range of the expression encompasses
        // the whole type being casted to (i.e. the warning is actually about overflow).
        Range exprRange = atypeFactory.getRange(exprAnno);
        if (castTypeKind == TypeKind.BYTE
            || castTypeKind == TypeKind.CHAR
            || castTypeKind == TypeKind.SHORT
            || castTypeKind == TypeKind.INT) {
          exprRange = NumberUtils.castRange(castType.getUnderlyingType(), exprRange);
        }
        if (castRange.equals(exprRange)) {
          return p;
        }
      }
    }
    return super.visitTypeCast(node, p);
  }

  /**
   * Overridden to issue errors at the appropriate place if an {@code IntRange} or {@code
   * ArrayLenRange} annotation has {@code from > to}. {@code from > to} either indicates a user
   * error when writing an annotation or an error in the checker's implementation, as {@code from}
   * should always be {@code <= to}. Note that additional checks are performed in {@link
   * #visitAnnotation(AnnotationTree, Void)}.
   *
   * @see #visitAnnotation(AnnotationTree, Void)
   */
  @Override
  public boolean validateType(Tree tree, AnnotatedTypeMirror type) {
    replaceSpecialIntRangeAnnotations(type);
    if (!super.validateType(tree, type)) {
      return false;
    }

    AnnotationMirror anno = type.getAnnotationInHierarchy(atypeFactory.UNKNOWNVAL);
    if (anno == null) {
      return false;
    }

    if (AnnotationUtils.areSameByName(anno, ValueAnnotatedTypeFactory.INTRANGE_NAME)) {
      if (TypesUtils.isIntegralPrimitiveOrBoxed(type.getUnderlyingType())) {
        long from = atypeFactory.getFromValueFromIntRange(type);
        long to = atypeFactory.getToValueFromIntRange(type);
        if (from > to) {
          checker.reportError(tree, "from.greater.than.to");
          return false;
        }
      } else {
        TypeMirror utype = type.getUnderlyingType();
        if (!TypesUtils.isObject(utype)
            && !TypesUtils.isDeclaredOfName(utype, "java.lang.Number")
            && !TypesUtils.isFloatingPoint(utype)) {
          checker.reportError(tree, "annotation.intrange.on.noninteger");
          return false;
        }
      }
    } else if (AnnotationUtils.areSameByName(anno, ValueAnnotatedTypeFactory.ARRAYLENRANGE_NAME)) {
      long from = getTypeFactory().getArrayLenRangeFromValue(anno);
      long to = getTypeFactory().getArrayLenRangeToValue(anno);
      if (from > to) {
        checker.reportError(tree, "from.greater.than.to");
        return false;
      }
    }

    return true;
  }

  /**
   * Returns true if an expression of the given type can be a compile-time constant value.
   *
   * @param tm a type
   * @return true if an expression of the given type can be a compile-time constant value
   */
  private boolean canBeConstant(TypeMirror tm) {
    return TypesUtils.isPrimitive(tm)
        || TypesUtils.isBoxedPrimitive(tm)
        || TypesUtils.isString(tm)
        || (tm.getKind() == TypeKind.ARRAY && canBeConstant(((ArrayType) tm).getComponentType()));
  }

  @Override
  public Void visitMethod(MethodTree node, Void p) {
    super.visitMethod(node, p);

    ExecutableElement method = TreeUtils.elementFromDeclaration(node);
    if (atypeFactory.getDeclAnnotation(method, StaticallyExecutable.class) != null) {
      // The method is annotated as @StaticallyExecutable.
      if (atypeFactory.getDeclAnnotation(method, Pure.class) == null) {
        checker.reportWarning(node, "statically.executable.not.pure");
      }
      TypeMirror returnType = method.getReturnType();
      if (returnType.getKind() != TypeKind.VOID && !canBeConstant(returnType)) {
        checker.reportError(node, "statically.executable.nonconstant.return.type", returnType);
      }

      // Ways to determine the receiver type.
      // 1. This definition of receiverType is null when receiver is implicit and method has
      //    class com.sun.tools.javac.code.Symbol$MethodSymbol.  WHY?
      //        TypeMirror receiverType = method.getReceiverType();
      //    The same is true of TreeUtils.elementFromDeclaration(node).getReceiverType()
      //    which seems to conflict with ExecutableType's documentation.
      // 2. Can't use the tree, because the receiver might not be explicit.
      // 3. Check whether method is static and use the declaring class.  Doesn't handle all
      //    cases, but handles the most common ones.
      TypeMirror receiverType = method.getReceiverType();
      // If the method is static, issue no warning.  This is incorrect in the case of a
      // constructor or a static method in an inner class.
      if (!ElementUtils.isStatic(method)) {
        receiverType = ElementUtils.getType(ElementUtils.enclosingTypeElement(method));
      }
      if (receiverType != null
          && receiverType.getKind() != TypeKind.NONE
          && !canBeConstant(receiverType)) {
        checker.reportError(
            node,
            "statically.executable.nonconstant.parameter.type",
            "this (the receiver)",
            returnType);
      }

      for (VariableElement param : method.getParameters()) {
        TypeMirror paramType = param.asType();
        if (paramType.getKind() != TypeKind.NONE && !canBeConstant(paramType)) {
          checker.reportError(
              node,
              "statically.executable.nonconstant.parameter.type",
              param.getSimpleName().toString(),
              returnType);
        }
      }
    }
    return null;
  }
}
