package org.checkerframework.common.value;

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.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.common.value.util.Range;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.typeannotator.TypeAnnotator;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TypeKindUtils;
import org.checkerframework.javacutil.TypesUtils;

/**
 * Performs pre-processing on annotations written by users, replacing illegal annotations by legal
 * ones.
 */
class ValueTypeAnnotator extends TypeAnnotator {

  /** The type factory to use. Shadows the field from the superclass with a more specific type. */
  @SuppressWarnings("HidingField")
  protected final ValueAnnotatedTypeFactory typeFactory;

  /**
   * Construct a new ValueTypeAnnotator.
   *
   * @param typeFactory the type factory to use
   */
  protected ValueTypeAnnotator(ValueAnnotatedTypeFactory typeFactory) {
    super(typeFactory);
    this.typeFactory = typeFactory;
  }

  @Override
  protected Void scan(AnnotatedTypeMirror type, Void aVoid) {
    replaceWithNewAnnoInSpecialCases(type);
    return super.scan(type, aVoid);
  }

  /**
   * This method performs pre-processing on annotations written by users.
   *
   * <p>If any *Val annotation has &gt; MAX_VALUES number of values provided, replaces the
   * annotation by @IntRange for integral types, @ArrayLenRange for arrays, @ArrayLen
   * or @ArrayLenRange for strings, and @UnknownVal for all other types. Works together with {@link
   * ValueVisitor#visitAnnotation(com.sun.source.tree.AnnotationTree, Void)} which issues warnings
   * to users in these cases.
   *
   * <p>If any @IntRange or @ArrayLenRange annotation has incorrect parameters, e.g. the value
   * "from" is greater than the value "to", replaces the annotation by {@code @BottomVal}. The
   * {@link ValueVisitor#visitAnnotation(com.sun.source.tree.AnnotationTree, Void)} raises an error
   * to users if the annotation was user-written.
   *
   * <p>If any @ArrayLen annotation has a negative number, replaces the annotation by {@code
   * BottomVal}. The {@link ValueVisitor#visitAnnotation(com.sun.source.tree.AnnotationTree, Void)}
   * raises an error to users if the annotation was user-written.
   *
   * <p>If a user only writes one side of an {@code IntRange} annotation, this method also computes
   * an appropriate default based on the underlying type for the other side of the range. For
   * instance, if the user writes {@code @IntRange(from = 1) short x;} then this method will
   * translate the annotation to {@code @IntRange(from = 1, to = Short.MAX_VALUE}.
   */
  private void replaceWithNewAnnoInSpecialCases(AnnotatedTypeMirror atm) {
    AnnotationMirror anno = atm.getAnnotationInHierarchy(typeFactory.UNKNOWNVAL);
    if (anno == null || anno.getElementValues().isEmpty()) {
      return;
    }

    if (AnnotationUtils.areSameByName(anno, ValueAnnotatedTypeFactory.INTVAL_NAME)) {
      List<Long> values = typeFactory.getIntValues(anno);
      if (values.size() > ValueAnnotatedTypeFactory.MAX_VALUES) {
        atm.replaceAnnotation(typeFactory.createIntRangeAnnotation(Range.create(values)));
      }
    } else if (AnnotationUtils.areSameByName(anno, ValueAnnotatedTypeFactory.ARRAYLEN_NAME)) {
      List<Integer> values = typeFactory.getArrayLength(anno);
      if (values.isEmpty()) {
        atm.replaceAnnotation(typeFactory.BOTTOMVAL);
      } else if (Collections.min(values) < 0) {
        atm.replaceAnnotation(typeFactory.BOTTOMVAL);
      } else if (values.size() > ValueAnnotatedTypeFactory.MAX_VALUES) {
        atm.replaceAnnotation(typeFactory.createArrayLenRangeAnnotation(Range.create(values)));
      }
    } else if (AnnotationUtils.areSameByName(anno, ValueAnnotatedTypeFactory.INTRANGE_NAME)) {
      TypeMirror underlyingType = atm.getUnderlyingType();
      // If the underlying type is neither a primitive integral type nor boxed integral type,
      // return without making changes. TypesUtils.isIntegralPrimitiveOrBoxed fails if passed
      // a non-primitive type that is not a declared type, so it cannot be called directly.
      if (!TypeKindUtils.isIntegral(underlyingType.getKind())
          && (underlyingType.getKind() != TypeKind.DECLARED
              || !TypesUtils.isIntegralPrimitiveOrBoxed(underlyingType))) {
        return;
      }

      // Compute appropriate defaults for integral ranges.
      long from = typeFactory.getFromValueFromIntRange(atm);
      long to = typeFactory.getToValueFromIntRange(atm);

      if (from > to) {
        // `from > to` either indicates a user error when writing an annotation or an error in the
        // checker's implementation. `-from` should always be <= to. ValueVisitor#validateType will
        // issue an error.
        atm.replaceAnnotation(typeFactory.BOTTOMVAL);
      } else {
        // Always do a replacement of the annotation here so that the defaults calculated above are
        // correctly added to the annotation (assuming the annotation is well-formed).
        atm.replaceAnnotation(typeFactory.createIntRangeAnnotation(from, to));
      }
    } else if (AnnotationUtils.areSameByName(anno, ValueAnnotatedTypeFactory.ARRAYLENRANGE_NAME)) {
      int from = typeFactory.getArrayLenRangeFromValue(anno);
      int to = typeFactory.getArrayLenRangeToValue(anno);
      if (from > to) {
        // `from > to` either indicates a user error when writing an annotation or an error in the
        // checker's implementation `-from` should always be <= to. ValueVisitor#validateType will
        // issue an error.
        atm.replaceAnnotation(typeFactory.BOTTOMVAL);
      } else if (from < 0) {
        // No array can have a length less than 0. Any time the type includes a from
        // less than zero, it must indicate imprecision in the checker.
        atm.replaceAnnotation(typeFactory.createArrayLenRangeAnnotation(0, to));
      }
    } else if (AnnotationUtils.areSameByName(anno, ValueAnnotatedTypeFactory.STRINGVAL_NAME)) {
      // The annotation is StringVal. If there are too many elements,
      // ArrayLen or ArrayLenRange is used.
      List<String> values = typeFactory.getStringValues(anno);

      if (values.size() > ValueAnnotatedTypeFactory.MAX_VALUES) {
        List<Integer> lengths = ValueCheckerUtils.getLengthsForStringValues(values);
        atm.replaceAnnotation(typeFactory.createArrayLenAnnotation(lengths));
      }

    } else if (AnnotationUtils.areSameByName(anno, ValueAnnotatedTypeFactory.MATCHES_REGEX_NAME)) {
      // If the annotation contains an invalid regex, replace it with bottom. ValueVisitor
      // will issue a warning where the annotation was written.
      List<String> regexes =
          AnnotationUtils.getElementValueArray(
              anno, typeFactory.matchesRegexValueElement, String.class);
      for (String regex : regexes) {
        try {
          Pattern.compile(regex);
        } catch (PatternSyntaxException pse) {
          atm.replaceAnnotation(typeFactory.BOTTOMVAL);
          break;
        }
      }
    } else {
      // In here the annotation is @*Val where (*) is not Int, String but other types
      // (Bool, Double, or Enum).
      // Therefore we extract its values in a generic way to check its size.
      @SuppressWarnings("deprecation") // concrete annotation class is not known
      List<Object> values =
          AnnotationUtils.getElementValueArray(anno, "value", Object.class, false);
      if (values.size() > ValueAnnotatedTypeFactory.MAX_VALUES) {
        atm.replaceAnnotation(typeFactory.UNKNOWNVAL);
      }
    }
  }
}
