package org.checkerframework.checker.i18nformatter;

import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.TypeCastTree;
import com.sun.source.util.SimpleTreeVisitor;
import java.util.List;
import java.util.Map;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.NullType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.SimpleElementVisitor7;
import javax.lang.model.util.SimpleTypeVisitor7;
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
import org.checkerframework.checker.formatter.FormatterTreeUtil.InvocationType;
import org.checkerframework.checker.formatter.FormatterTreeUtil.Result;
import org.checkerframework.checker.i18nformatter.qual.I18nChecksFormat;
import org.checkerframework.checker.i18nformatter.qual.I18nConversionCategory;
import org.checkerframework.checker.i18nformatter.qual.I18nFormat;
import org.checkerframework.checker.i18nformatter.qual.I18nFormatFor;
import org.checkerframework.checker.i18nformatter.qual.I18nInvalidFormat;
import org.checkerframework.checker.i18nformatter.qual.I18nMakeFormat;
import org.checkerframework.checker.i18nformatter.qual.I18nValidFormat;
import org.checkerframework.checker.i18nformatter.util.I18nFormatUtil;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.signature.qual.BinaryName;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.dataflow.cfg.node.ArrayCreationNode;
import org.checkerframework.dataflow.cfg.node.FieldAccessNode;
import org.checkerframework.dataflow.cfg.node.MethodInvocationNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.StringLiteralNode;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.util.JavaExpressionParseUtil;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TreeUtils;

/**
 * This class provides a collection of utilities to ease working with syntax trees that have
 * something to do with I18nFormatters.
 *
 * @checker_framework.manual #i18n-formatter-checker Internationalization Format String Checker
 */
public class I18nFormatterTreeUtil {
  /** The checker. */
  public final BaseTypeChecker checker;
  /** The processing environment. */
  public final ProcessingEnvironment processingEnv;

  /** The value() element/field of an @I18nFormat annotation. */
  protected final ExecutableElement i18nFormatValueElement;
  /** The value() element/field of an @I18nFormatFor annotation. */
  protected final ExecutableElement i18nFormatForValueElement;
  /** The value() element/field of an @I18nInvalidFormat annotation. */
  protected final ExecutableElement i18nInvalidFormatValueElement;

  /**
   * Creates a new I18nFormatterTreeUtil.
   *
   * @param checker the checker
   */
  public I18nFormatterTreeUtil(BaseTypeChecker checker) {
    this.checker = checker;
    this.processingEnv = checker.getProcessingEnvironment();
    i18nFormatValueElement = TreeUtils.getMethod(I18nFormat.class, "value", 0, processingEnv);
    i18nFormatForValueElement = TreeUtils.getMethod(I18nFormatFor.class, "value", 0, processingEnv);
    i18nInvalidFormatValueElement =
        TreeUtils.getMethod(I18nInvalidFormat.class, "value", 0, processingEnv);
  }

  /** Describe the format annotation type. */
  public enum FormatType {
    I18NINVALID,
    I18NFORMAT,
    I18NFORMATFOR
  }

  /**
   * Takes an exception that describes an invalid formatter string and returns a syntax trees
   * element that represents a {@link I18nInvalidFormat} annotation with the exception's error
   * message as value.
   */
  public AnnotationMirror exceptionToInvalidFormatAnnotation(IllegalArgumentException ex) {
    return stringToInvalidFormatAnnotation(ex.getMessage());
  }

  /**
   * Creates an {@link I18nInvalidFormat} annotation with the given string as its value.
   *
   * @param invalidFormatString an invalid formatter string
   * @return an {@link I18nInvalidFormat} annotation with the given string as its value
   */
  // package-private
  AnnotationMirror stringToInvalidFormatAnnotation(String invalidFormatString) {
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, I18nInvalidFormat.class);
    builder.setValue("value", invalidFormatString);
    return builder.build();
  }

  /**
   * Gets the value() element/field out of an I18nInvalidFormat annotation.
   *
   * @param anno an I18nInvalidFormat annotation
   * @return its value() element/field, or null if it does not have one
   */
  /*package-visible*/
  @Nullable String getI18nInvalidFormatValue(AnnotationMirror anno) {
    return AnnotationUtils.getElementValue(anno, i18nInvalidFormatValueElement, String.class, null);
  }

  /**
   * Gets the value() element/field out of an I18NFormatFor annotation.
   *
   * @param anno an I18NFormatFor annotation
   * @return its value() element/field
   */
  /*package-visible*/ String getI18nFormatForValue(AnnotationMirror anno) {
    return AnnotationUtils.getElementValue(anno, i18nFormatForValueElement, String.class);
  }

  /**
   * Takes a syntax tree element that represents a {@link I18nInvalidFormat} annotation, and returns
   * its value.
   *
   * @param anno an I18nInvalidFormat annotation
   * @return its value() element/field, within double-quotes
   */
  public String invalidFormatAnnotationToErrorMessage(AnnotationMirror anno) {
    return "\"" + getI18nInvalidFormatValue(anno) + "\"";
  }

  /**
   * Creates a {@code @}{@link I18nFormat} annotation with the given list as its value.
   *
   * @param args conversion categories for the {@code @Format} annotation
   * @return a {@code @}{@link I18nFormat} annotation with the given list as its value
   */
  public AnnotationMirror categoriesToFormatAnnotation(I18nConversionCategory[] args) {
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, I18nFormat.class);
    builder.setValue("value", args);
    return builder.build();
  }

  /**
   * Takes an {@code @}{@link I18nFormat} annotation, and returns its {@code value} element
   *
   * @param anno an {@code @}{@link I18nFormat} annotation
   * @return the {@code @}{@link I18nFormat} annotation's {@code value} element
   */
  public I18nConversionCategory[] formatAnnotationToCategories(AnnotationMirror anno) {
    return AnnotationUtils.getElementValueEnumArray(
        anno, i18nFormatValueElement, I18nConversionCategory.class);
  }

  /**
   * Returns true if the call is to a method with the @I18nChecksFormat annotation. An example of
   * such a method is I18nFormatUtil.hasFormat.
   */
  public boolean isHasFormatCall(MethodInvocationNode node, AnnotatedTypeFactory atypeFactory) {
    ExecutableElement method = node.getTarget().getMethod();
    AnnotationMirror anno = atypeFactory.getDeclAnnotation(method, I18nChecksFormat.class);
    return anno != null;
  }

  /**
   * Returns true if the call is to a method with the @I18nValidFormat annotation. An example of
   * such a method is I18nFormatUtil.isFormat.
   */
  public boolean isIsFormatCall(MethodInvocationNode node, AnnotatedTypeFactory atypeFactory) {
    ExecutableElement method = node.getTarget().getMethod();
    AnnotationMirror anno = atypeFactory.getDeclAnnotation(method, I18nValidFormat.class);
    return anno != null;
  }

  /**
   * Returns true if the call is to a method with the @I18nMakeFormat annotation. An example of such
   * a method is ResourceBundle.getString.
   */
  public boolean isMakeFormatCall(MethodInvocationNode node, AnnotatedTypeFactory atypeFactory) {
    ExecutableElement method = node.getTarget().getMethod();
    AnnotationMirror anno = atypeFactory.getDeclAnnotation(method, I18nMakeFormat.class);
    return anno != null;
  }

  /**
   * Reports an error.
   *
   * @param res used for source location information
   * @param msgKey the diagnostic message key
   * @param args arguments to the diagnostic message
   */
  public final void failure(Result<?> res, @CompilerMessageKey String msgKey, Object... args) {
    checker.reportError(res.location, msgKey, args);
  }

  /**
   * Reports a warning.
   *
   * @param res used for source location information
   * @param msgKey the diagnostic message key
   * @param args arguments to the diagnostic message
   */
  public final void warning(Result<?> res, @CompilerMessageKey String msgKey, Object... args) {
    checker.reportWarning(res.location, msgKey, args);
  }

  private I18nConversionCategory[] asFormatCallCategoriesLowLevel(MethodInvocationNode node) {
    Node vararg = node.getArgument(1);
    if (vararg instanceof ArrayCreationNode) {
      List<Node> convs = ((ArrayCreationNode) vararg).getInitializers();
      I18nConversionCategory[] res = new I18nConversionCategory[convs.size()];
      for (int i = 0; i < convs.size(); i++) {
        Node conv = convs.get(i);
        if (conv instanceof FieldAccessNode) {
          if (typeMirrorToClass(((FieldAccessNode) conv).getType())
              == I18nConversionCategory.class) {
            res[i] = I18nConversionCategory.valueOf(((FieldAccessNode) conv).getFieldName());
            continue; /* avoid returning null */
          }
        }
        return null;
      }
      return res;
    }
    return null;
  }

  public Result<I18nConversionCategory[]> getHasFormatCallCategories(MethodInvocationNode node) {
    return new Result<>(asFormatCallCategoriesLowLevel(node), node.getTree());
  }

  public Result<I18nConversionCategory[]> makeFormatCallCategories(
      MethodInvocationNode node, I18nFormatterAnnotatedTypeFactory atypeFactory) {
    Map<String, String> translations = atypeFactory.translations;
    Node firstParam = node.getArgument(0);
    Result<I18nConversionCategory[]> ret = new Result<>(null, node.getTree());

    // Now only work with a literal string
    if (firstParam instanceof StringLiteralNode) {
      String s = ((StringLiteralNode) firstParam).getValue();
      if (translations.containsKey(s)) {
        String value = translations.get(s);
        ret = new Result<>(I18nFormatUtil.formatParameterCategories(value), node.getTree());
      }
    }
    return ret;
  }

  /**
   * Returns an I18nFormatCall instance, only if there is an {@code @I18nFormatFor} annotation.
   * Otherwise, returns null.
   *
   * @param tree method invocation tree
   * @param atypeFactory type factory
   * @return an I18nFormatCall instance, only if there is an {@code @I18nFormatFor} annotation.
   *     Otherwise, returns null.
   */
  public @Nullable I18nFormatCall createFormatForCall(
      MethodInvocationTree tree, I18nFormatterAnnotatedTypeFactory atypeFactory) {
    ExecutableElement method = TreeUtils.elementFromUse(tree);
    AnnotatedExecutableType methodAnno = atypeFactory.getAnnotatedType(method);
    for (AnnotatedTypeMirror paramType : methodAnno.getParameterTypes()) {
      // find @FormatFor
      if (paramType.getAnnotation(I18nFormatFor.class) != null) {
        return atypeFactory.treeUtil.new I18nFormatCall(tree, atypeFactory);
      }
    }
    return null;
  }

  /**
   * Represents a format method invocation in the syntax tree.
   *
   * <p>An I18nFormatCall instance can only be instantiated by the createFormatForCall method.
   */
  public class I18nFormatCall {

    /** The AST node for the call. */
    private final MethodInvocationTree tree;
    /** The format string argument. */
    private ExpressionTree formatArg;
    /** The type factory. */
    private final AnnotatedTypeFactory atypeFactory;
    /** The arguments to the format string. */
    private List<? extends ExpressionTree> args;
    /** Extra description for error messages. */
    private String invalidMessage;

    /** The type of the format string formal parameter. */
    private AnnotatedTypeMirror formatAnno;

    /**
     * Creates an {@code I18nFormatCall} for the given method invocation tree.
     *
     * @param tree method invocation tree
     * @param atypeFactory type factory
     */
    public I18nFormatCall(MethodInvocationTree tree, AnnotatedTypeFactory atypeFactory) {
      this.tree = tree;
      this.atypeFactory = atypeFactory;
      List<? extends ExpressionTree> theargs = tree.getArguments();
      this.args = null;
      ExecutableElement method = TreeUtils.elementFromUse(tree);
      AnnotatedExecutableType methodAnno = atypeFactory.getAnnotatedType(method);
      initialCheck(theargs, method, methodAnno);
    }

    /**
     * Returns the AST node for the call.
     *
     * @return the AST node for the call
     */
    public MethodInvocationTree getTree() {
      return tree;
    }

    @Override
    public String toString() {
      return this.tree.toString();
    }

    /**
     * This method checks the validity of the FormatFor. If it is valid, this.args will be set to
     * the correct parameter arguments. Otherwise, it will be still null.
     *
     * @param theargs arguments to the format method call
     * @param method the ExecutableElement of the format method
     * @param methodAnno annotated type of {@code method}
     */
    private void initialCheck(
        List<? extends ExpressionTree> theargs,
        ExecutableElement method,
        AnnotatedExecutableType methodAnno) {
      // paramIndex is a 0-based index
      int paramIndex = -1;
      int i = 0;
      for (AnnotatedTypeMirror paramType : methodAnno.getParameterTypes()) {
        if (paramType.getAnnotation(I18nFormatFor.class) != null) {
          this.formatArg = theargs.get(i);
          this.formatAnno = atypeFactory.getAnnotatedType(formatArg);

          if (typeMirrorToClass(paramType.getUnderlyingType()) != String.class) {
            // Invalid FormatFor invocation
            return;
          }

          String formatforArg = getI18nFormatForValue(paramType.getAnnotation(I18nFormatFor.class));

          paramIndex = JavaExpressionParseUtil.parameterIndex(formatforArg);
          if (paramIndex == -1) {
            // report errors here
            checker.reportError(tree, "i18nformat.formatfor");
          } else {
            paramIndex--;
          }
          break;
        }
        i++;
      }

      if (paramIndex != -1) {
        VariableElement param = method.getParameters().get(paramIndex);
        if (param.asType().getKind() == TypeKind.ARRAY) {
          this.args = theargs.subList(paramIndex, theargs.size());
        } else {
          this.args = theargs.subList(paramIndex, paramIndex + 1);
        }
      }
    }

    public Result<FormatType> getFormatType() {
      FormatType type;
      if (isValidFormatForInvocation()) {
        if (formatAnno.hasAnnotation(I18nFormat.class)) {
          type = FormatType.I18NFORMAT;
        } else if (formatAnno.hasAnnotation(I18nFormatFor.class)) {
          type = FormatType.I18NFORMATFOR;
        } else {
          type = FormatType.I18NINVALID;
          invalidMessage = "(is a @I18nFormat annotation missing?)";
          AnnotationMirror inv = formatAnno.getAnnotation(I18nInvalidFormat.class);
          if (inv != null) {
            invalidMessage = getI18nInvalidFormatValue(inv);
          }
        }
      } else {
        // If the FormatFor is invalid, it's still I18nFormatFor type but invalid,
        // and we can't do anything else
        type = FormatType.I18NFORMATFOR;
      }
      return new Result<>(type, formatArg);
    }

    public final String getInvalidError() {
      return invalidMessage;
    }

    public boolean isValidFormatForInvocation() {
      return this.args != null;
    }

    /**
     * Returns the type of method invocation.
     *
     * @see InvocationType
     */
    public final Result<InvocationType> getInvocationType() {
      InvocationType type = InvocationType.VARARG;

      if (args.size() == 1) {
        final ExpressionTree first = args.get(0);
        TypeMirror argType = atypeFactory.getAnnotatedType(first).getUnderlyingType();
        // figure out if argType is an array
        type =
            argType.accept(
                new SimpleTypeVisitor7<InvocationType, Class<Void>>() {
                  @Override
                  protected InvocationType defaultAction(TypeMirror e, Class<Void> p) {
                    // not an array
                    return InvocationType.VARARG;
                  }

                  @Override
                  public InvocationType visitArray(ArrayType t, Class<Void> p) {
                    // it's an array, now figure out if it's a
                    // (Object[])null array
                    return first.accept(
                        new SimpleTreeVisitor<InvocationType, Class<Void>>() {
                          @Override
                          protected InvocationType defaultAction(Tree node, Class<Void> p) {
                            // just a normal array
                            return InvocationType.ARRAY;
                          }

                          @Override
                          public InvocationType visitTypeCast(TypeCastTree node, Class<Void> p) {
                            // it's a (Object[])null
                            return atypeFactory
                                        .getAnnotatedType(node.getExpression())
                                        .getUnderlyingType()
                                        .getKind()
                                    == TypeKind.NULL
                                ? InvocationType.NULLARRAY
                                : InvocationType.ARRAY;
                          }
                        },
                        p);
                  }

                  @Override
                  public InvocationType visitNull(NullType t, Class<Void> p) {
                    return InvocationType.NULLARRAY;
                  }
                },
                Void.TYPE);
      }

      ExpressionTree loc;
      loc = tree.getMethodSelect();
      if (type != InvocationType.VARARG && !args.isEmpty()) {
        loc = args.get(0);
      }
      return new Result<>(type, loc);
    }

    public Result<FormatType> getInvalidInvocationType() {
      return new Result<>(FormatType.I18NFORMATFOR, formatArg);
    }

    /**
     * Returns the conversion category for every parameter.
     *
     * @see I18nConversionCategory
     */
    public final I18nConversionCategory[] getFormatCategories() {
      AnnotationMirror anno = formatAnno.getAnnotation(I18nFormat.class);
      return formatAnnotationToCategories(anno);
    }

    public final Result<TypeMirror>[] getParamTypes() {
      // One to suppress warning in javac, the other to suppress warning in Eclipse...
      @SuppressWarnings({"rawtypes", "unchecked"})
      Result<TypeMirror>[] res = new Result[args.size()];
      for (int i = 0; i < res.length; ++i) {
        ExpressionTree arg = args.get(i);
        TypeMirror argType = atypeFactory.getAnnotatedType(arg).getUnderlyingType();
        res[i] = new Result<>(argType, arg);
      }
      return res;
    }

    public boolean isValidParameter(I18nConversionCategory formatCat, TypeMirror paramType) {
      Class<? extends Object> type = typeMirrorToClass(paramType);
      if (type == null) {
        // we did not recognize the parameter type
        return false;
      }
      return formatCat.isAssignableFrom(type);
    }
  }

  /** Converts a TypeMirror to a Class. */
  private static class TypeMirrorToClassVisitor
      extends SimpleTypeVisitor7<Class<? extends Object>, Class<Void>> {
    @Override
    public Class<? extends Object> visitPrimitive(PrimitiveType t, Class<Void> v) {
      switch (t.getKind()) {
        case BOOLEAN:
          return Boolean.class;
        case BYTE:
          return Byte.class;
        case CHAR:
          return Character.class;
        case SHORT:
          return Short.class;
        case INT:
          return Integer.class;
        case LONG:
          return Long.class;
        case FLOAT:
          return Float.class;
        case DOUBLE:
          return Double.class;
        default:
          return null;
      }
    }

    @Override
    public Class<? extends Object> visitDeclared(DeclaredType dt, Class<Void> v) {
      return dt.asElement()
          .accept(
              new SimpleElementVisitor7<Class<? extends Object>, Class<Void>>() {
                @Override
                public Class<? extends Object> visitType(TypeElement e, Class<Void> v) {
                  try {
                    @SuppressWarnings("signature") // https://tinyurl.com/cfissue/658:
                    // Name.toString should be @PolySignature
                    @BinaryName String cname = e.getQualifiedName().toString();
                    return Class.forName(cname);
                  } catch (ClassNotFoundException e1) {
                    return null; // the lookup should work for all
                    // the classes we care about
                  }
                }
              },
              Void.TYPE);
    }
  }

  /** The singleton instance of TypeMirrorToClassVisitor. */
  private static TypeMirrorToClassVisitor typeMirrorToClassVisitor = new TypeMirrorToClassVisitor();

  /**
   * Converts a TypeMirror to a Class.
   *
   * @param type a TypeMirror
   * @return the class corresponding to the argument
   */
  private static final Class<? extends Object> typeMirrorToClass(final TypeMirror type) {
    return type.accept(typeMirrorToClassVisitor, Void.TYPE);
  }
}
