package org.checkerframework.framework.type;

import com.sun.tools.javac.code.Type;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
import javax.lang.model.element.Element;
import javax.lang.model.type.TypeKind;
import org.checkerframework.dataflow.qual.SideEffectFree;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedNoType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedNullType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedPrimitiveType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedUnionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import org.checkerframework.framework.type.visitor.AnnotatedTypeVisitor;
import org.checkerframework.framework.util.AnnotationFormatter;
import org.checkerframework.framework.util.DefaultAnnotationFormatter;
import org.checkerframework.javacutil.TypeAnnotationUtils;
import org.checkerframework.javacutil.TypesUtils;

/**
 * An AnnotatedTypeFormatter used by default by all AnnotatedTypeFactory (and therefore all
 * annotated types).
 *
 * @see org.checkerframework.framework.type.AnnotatedTypeFormatter
 * @see org.checkerframework.framework.type.AnnotatedTypeMirror#toString
 */
public class DefaultAnnotatedTypeFormatter implements AnnotatedTypeFormatter {
  protected final FormattingVisitor formattingVisitor;

  /**
   * Constructs a DefaultAnnotatedTypeFormatter that does not print invisible annotations by
   * default.
   */
  public DefaultAnnotatedTypeFormatter() {
    this(new DefaultAnnotationFormatter(), true, false);
  }

  /**
   * @param printVerboseGenerics for type parameters, their uses, and wildcards, print more
   *     information
   * @param defaultPrintInvisibleAnnos whether or not this AnnotatedTypeFormatter should print
   *     invisible annotations
   */
  public DefaultAnnotatedTypeFormatter(
      boolean printVerboseGenerics, boolean defaultPrintInvisibleAnnos) {
    this(new DefaultAnnotationFormatter(), printVerboseGenerics, defaultPrintInvisibleAnnos);
  }

  /**
   * @param formatter an object that converts annotation mirrors to strings
   * @param printVerboseGenerics for type parameters, their uses, and wildcards, print more
   *     information
   * @param defaultPrintInvisibleAnnos whether or not this AnnotatedTypeFormatter should print
   *     invisible annotations
   */
  public DefaultAnnotatedTypeFormatter(
      AnnotationFormatter formatter,
      boolean printVerboseGenerics,
      boolean defaultPrintInvisibleAnnos) {
    this(new FormattingVisitor(formatter, printVerboseGenerics, defaultPrintInvisibleAnnos));
  }

  /**
   * Used by subclasses and other constructors to specify the underlying implementation of this
   * DefaultAnnotatedTypeFormatter.
   */
  protected DefaultAnnotatedTypeFormatter(FormattingVisitor visitor) {
    this.formattingVisitor = visitor;
  }

  @Override
  public String format(final AnnotatedTypeMirror type) {
    formattingVisitor.resetPrintVerboseSettings();
    return formattingVisitor.visit(type);
  }

  @Override
  public String format(final AnnotatedTypeMirror type, final boolean printVerbose) {
    formattingVisitor.setVerboseSettings(printVerbose);
    return formattingVisitor.visit(type);
  }

  /** A scanning visitor that prints the entire AnnotatedTypeMirror passed to visit. */
  protected static class FormattingVisitor
      implements AnnotatedTypeVisitor<String, Set<AnnotatedTypeMirror>> {

    /** The object responsible for converting annotations to strings. */
    protected final AnnotationFormatter annoFormatter;

    /**
     * Represents whether or not invisible annotations should be printed if the client of this class
     * does not use the printInvisibleAnnos parameter.
     */
    protected final boolean defaultInvisiblesSetting;

    /**
     * For a given call to format, this setting specifies whether or not to printInvisibles. If a
     * user did not specify a printInvisible parameter in the call to format then this value will
     * equal DefaultAnnotatedTypeFormatter.defaultInvisibleSettings for this object
     */
    protected boolean currentPrintInvisibleSetting;

    /** Default value of currentPrintVerboseGenerics. */
    protected final boolean defaultPrintVerboseGenerics;

    /**
     * Prints type variables in a less ambiguous manner using [] to delimit them. Always prints both
     * bounds even if they lower bound is an AnnotatedNull type.
     */
    protected boolean currentPrintVerboseGenerics;

    public FormattingVisitor(
        AnnotationFormatter annoFormatter,
        boolean printVerboseGenerics,
        boolean defaultInvisiblesSetting) {
      this.annoFormatter = annoFormatter;
      this.defaultPrintVerboseGenerics = printVerboseGenerics;
      this.currentPrintVerboseGenerics = printVerboseGenerics;
      this.defaultInvisiblesSetting = defaultInvisiblesSetting;
      this.currentPrintInvisibleSetting = false;
    }

    /** Set the current verbose settings to use while printing. */
    protected void setVerboseSettings(boolean printVerbose) {
      this.currentPrintInvisibleSetting = printVerbose;
      this.currentPrintVerboseGenerics = printVerbose;
    }

    /** Set verbose settings to the default. */
    protected void resetPrintVerboseSettings() {
      this.currentPrintInvisibleSetting = defaultInvisiblesSetting;
      this.currentPrintVerboseGenerics = defaultPrintVerboseGenerics;
    }

    /**
     * Print, to sb, {@code keyWord} followed by {@code field}. NULL types are substituted with
     * their annotations followed by " Void"
     */
    @SideEffectFree
    protected void printBound(
        final String keyWord,
        final AnnotatedTypeMirror field,
        final Set<AnnotatedTypeMirror> visiting,
        final StringBuilder sb) {
      if (!currentPrintVerboseGenerics && (field == null || field.getKind() == TypeKind.NULL)) {
        return;
      }

      sb.append(" ");
      sb.append(keyWord);
      sb.append(" ");

      if (field == null) {
        sb.append("<null>");
      } else if (field.getKind() != TypeKind.NULL) {
        sb.append(visit(field, visiting));
      } else {
        sb.append(
            annoFormatter.formatAnnotationString(
                field.getAnnotations(), currentPrintInvisibleSetting));
        sb.append("Void");
      }
    }

    @SideEffectFree
    @Override
    public String visit(AnnotatedTypeMirror type) {
      return type.accept(this, Collections.newSetFromMap(new IdentityHashMap<>()));
    }

    @Override
    public String visit(AnnotatedTypeMirror type, Set<AnnotatedTypeMirror> annotatedTypeVariables) {
      return type.accept(this, annotatedTypeVariables);
    }

    @Override
    public String visitDeclared(AnnotatedDeclaredType type, Set<AnnotatedTypeMirror> visiting) {
      StringBuilder sb = new StringBuilder();
      if (type.isDeclaration() && currentPrintInvisibleSetting) {
        sb.append("/*DECL*/ ");
      }
      if (type.getEnclosingType() != null) {
        sb.append(this.visit(type.getEnclosingType(), visiting));
        sb.append('.');
      }
      final Element typeElt = type.getUnderlyingType().asElement();
      String smpl = typeElt.getSimpleName().toString();
      if (smpl.isEmpty()) {
        // For anonymous classes smpl is empty - toString
        // of the element is more useful.
        smpl = typeElt.toString();
      }
      sb.append(
          annoFormatter.formatAnnotationString(
              type.getAnnotations(), currentPrintInvisibleSetting));
      sb.append(smpl);

      if (type.typeArgs != null) {
        // getTypeArguments sets the field if it does not already exist.
        final List<AnnotatedTypeMirror> typeArgs = type.typeArgs;
        if (!typeArgs.isEmpty()) {
          StringJoiner sj = new StringJoiner(", ", "<", ">");
          for (AnnotatedTypeMirror typeArg : typeArgs) {
            sj.add(visit(typeArg, visiting));
          }
          sb.append(sj);
        }
      }
      return sb.toString();
    }

    @Override
    public String visitIntersection(
        AnnotatedIntersectionType type, Set<AnnotatedTypeMirror> visiting) {
      StringBuilder sb = new StringBuilder();

      boolean isFirst = true;
      for (AnnotatedTypeMirror bound : type.getBounds()) {
        if (!isFirst) {
          sb.append(" & ");
        }
        sb.append(visit(bound, visiting));
        isFirst = false;
      }
      return sb.toString();
    }

    @Override
    public String visitUnion(AnnotatedUnionType type, Set<AnnotatedTypeMirror> visiting) {
      StringBuilder sb = new StringBuilder();

      boolean isFirst = true;
      for (AnnotatedDeclaredType adt : type.getAlternatives()) {
        if (!isFirst) {
          sb.append(" | ");
        }
        sb.append(visit(adt, visiting));
        isFirst = false;
      }
      return sb.toString();
    }

    @Override
    public String visitExecutable(AnnotatedExecutableType type, Set<AnnotatedTypeMirror> visiting) {
      StringBuilder sb = new StringBuilder();
      if (!type.getTypeVariables().isEmpty()) {
        StringJoiner sj = new StringJoiner(", ", "<", "> ");
        for (AnnotatedTypeVariable atv : type.getTypeVariables()) {
          sj.add(visit(atv, visiting));
        }
        sb.append(sj.toString());
      }
      if (type.getReturnType() != null) {
        sb.append(visit(type.getReturnType(), visiting));
      } else {
        sb.append("<UNKNOWNRETURN>");
      }
      sb.append(' ');
      if (type.getElement() != null) {
        sb.append(type.getElement().getSimpleName());
      } else {
        sb.append("METHOD");
      }
      sb.append('(');
      AnnotatedDeclaredType rcv = type.getReceiverType();
      if (rcv != null) {
        sb.append(visit(rcv, visiting));
        sb.append(" this");
      }
      if (!type.getParameterTypes().isEmpty()) {
        int p = 0;
        for (AnnotatedTypeMirror atm : type.getParameterTypes()) {
          if (rcv != null || p > 0) {
            sb.append(", ");
          }
          sb.append(visit(atm, visiting));
          // Output some parameter names to make it look more like a method.
          // TODO: go to the element and look up real parameter names, maybe.
          sb.append(" p");
          sb.append(p++);
        }
      }
      sb.append(')');
      if (!type.getThrownTypes().isEmpty()) {
        sb.append(" throws ");
        for (AnnotatedTypeMirror atm : type.getThrownTypes()) {
          sb.append(visit(atm, visiting));
        }
      }
      return sb.toString();
    }

    @Override
    public String visitArray(AnnotatedArrayType type, Set<AnnotatedTypeMirror> visiting) {
      StringBuilder sb = new StringBuilder();

      AnnotatedArrayType array = type;
      AnnotatedTypeMirror component;
      while (true) {
        component = array.getComponentType();
        if (!array.getAnnotations().isEmpty()) {
          sb.append(' ');
          sb.append(
              annoFormatter.formatAnnotationString(
                  array.getAnnotations(), currentPrintInvisibleSetting));
        }
        sb.append("[]");
        if (!(component instanceof AnnotatedArrayType)) {
          sb.insert(0, visit(component, visiting));
          break;
        }
        array = (AnnotatedArrayType) component;
      }
      return sb.toString();
    }

    @Override
    public String visitTypeVariable(AnnotatedTypeVariable type, Set<AnnotatedTypeMirror> visiting) {
      StringBuilder sb = new StringBuilder();
      if (TypesUtils.isCaptured(type.underlyingType)) {
        String underlyingType = type.underlyingType.toString();
        // underlyingType has this form: "capture#826 of ? extends java.lang.Object".
        // We output only the "capture#826" part.
        // NOTE: The number is the hash code of the captured type, so it's nondeterministic, but it
        // is still important to print it in order to tell the difference between two captured
        // types.
        sb.append(underlyingType, 0, underlyingType.indexOf(" of "));
      } else {
        sb.append(type.underlyingType);
      }

      if (!visiting.contains(type)) {
        if (type.isDeclaration() && currentPrintInvisibleSetting) {
          sb.append("/*DECL*/ ");
        }

        try {
          visiting.add(type);
          if (currentPrintVerboseGenerics) {
            sb.append("[");
          }
          printBound("extends", type.getUpperBoundField(), visiting, sb);
          printBound("super", type.getLowerBoundField(), visiting, sb);
          if (currentPrintVerboseGenerics) {
            sb.append("]");
          }

        } finally {
          visiting.remove(type);
        }
      }
      return sb.toString();
    }

    @SideEffectFree
    @Override
    public String visitPrimitive(AnnotatedPrimitiveType type, Set<AnnotatedTypeMirror> visiting) {
      return formatFlatType(type);
    }

    @SideEffectFree
    @Override
    public String visitNoType(AnnotatedNoType type, Set<AnnotatedTypeMirror> visiting) {
      return formatFlatType(type);
    }

    @SideEffectFree
    @Override
    public String visitNull(AnnotatedNullType type, Set<AnnotatedTypeMirror> visiting) {
      return annoFormatter.formatAnnotationString(
              type.getAnnotations(), currentPrintInvisibleSetting)
          + "NullType";
    }

    @Override
    public String visitWildcard(AnnotatedWildcardType type, Set<AnnotatedTypeMirror> visiting) {
      StringBuilder sb = new StringBuilder();
      if (type.isUninferredTypeArgument()) {
        sb.append("/*INFERENCE FAILED for:*/ ");
      }

      sb.append(
          annoFormatter.formatAnnotationString(
              type.getAnnotationsField(), currentPrintInvisibleSetting));

      sb.append("?");
      if (!visiting.contains(type)) {

        try {
          visiting.add(type);

          if (currentPrintVerboseGenerics) {
            sb.append("[");
          }
          printBound("extends", type.getExtendsBoundField(), visiting, sb);
          printBound("super", type.getSuperBoundField(), visiting, sb);
          if (currentPrintVerboseGenerics) {
            sb.append("]");
          }

        } finally {
          visiting.remove(type);
        }
      }
      return sb.toString();
    }

    @SideEffectFree
    protected String formatFlatType(final AnnotatedTypeMirror flatType) {
      return annoFormatter.formatAnnotationString(
              flatType.getAnnotations(), currentPrintInvisibleSetting)
          + TypeAnnotationUtils.unannotatedType((Type) flatType.getUnderlyingType());
    }
  }
}
