package org.checkerframework.framework.ajava;

import com.github.javaparser.Position;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
import com.github.javaparser.ast.type.ArrayType;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.printer.DefaultPrettyPrinter;
import com.github.javaparser.utils.Pair;
import com.sun.source.util.JavacTask;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;
import org.checkerframework.checker.signature.qual.DotSeparatedIdentifiers;
import org.checkerframework.checker.signature.qual.FullyQualifiedName;
import org.checkerframework.framework.stub.AnnotationFileParser;
import org.checkerframework.framework.util.JavaParserUtil;
import org.plumelib.util.FilesPlume;

/** This program inserts annotations from an ajava file into a Java file. See {@link #main}. */
public class InsertAjavaAnnotations {
  /** Element utilities. */
  private Elements elements;

  /**
   * Constructs an {@code InsertAjavaAnnotations} using the given {@code Elements} instance.
   *
   * @param elements an instance of {@code Elements}
   */
  public InsertAjavaAnnotations(Elements elements) {
    this.elements = elements;
  }

  /**
   * Gets an instance of {@code Elements} from the current Java compiler.
   *
   * @return Element utilities
   */
  private static Elements createElements() {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    if (compiler == null) {
      System.err.println("Could not get compiler instance");
      System.exit(1);
    }

    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
    JavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
    if (fileManager == null) {
      System.err.println("Could not get file manager");
      System.exit(1);
    }

    CompilationTask cTask =
        compiler.getTask(
            null, fileManager, diagnostics, Collections.emptyList(), null, Collections.emptyList());
    if (!(cTask instanceof JavacTask)) {
      System.err.println("Could not get a valid JavacTask: " + cTask.getClass());
      System.exit(1);
    }

    return ((JavacTask) cTask).getElements();
  }

  /** Represents some text to be inserted at a file and its location. */
  private static class Insertion {
    /** Offset of the insertion in the file, measured in characters from the beginning. */
    public int position;
    /** The contents of the insertion. */
    public String contents;
    /** Whether the insertion should be on its own separate line. */
    public boolean ownLine;

    /**
     * Constructs an insertion with the given position and contents.
     *
     * @param position offset of the insertion in the file
     * @param contents contents of the insertion
     */
    public Insertion(int position, String contents) {
      this(position, contents, false);
    }

    /**
     * Constructs an insertion with the given position and contents.
     *
     * @param position offset of the insertion in the file
     * @param contents contents of the insertion
     * @param ownLine true if this insertion should appear on its own separate line (doesn't affect
     *     the contents of the insertion)
     */
    public Insertion(int position, String contents, boolean ownLine) {
      this.position = position;
      this.contents = contents;
      this.ownLine = ownLine;
    }

    @Override
    public String toString() {
      return "Insertion [contents=" + contents + ", position=" + position + "]";
    }
  }

  /**
   * Given two JavaParser ASTs representing the same Java file but with differing annotations,
   * stores a list of {@link Insertion}s. The {@link Insertion}s represent how to textually modify
   * the file of the second AST to insert all annotations in the first AST into the second AST, but
   * this class doesn't modify the second AST itself. To use this class, call {@link
   * #visit(CompilationUnit, Node)} on a pair of ASTs and then use the contents of {@link
   * #insertions}.
   */
  private class BuildInsertionsVisitor extends DoubleJavaParserVisitor {
    /**
     * The set of annotations found in the file. Keys are both fully-qualified and simple names.
     * Contains an entry for the fully qualified name of each annotation and, if it was imported,
     * its simple name.
     *
     * <p>The map is populated from import statements and also when parsing a file that uses the
     * fully qualified name of an annotation it doesn't import.
     */
    private Map<String, TypeElement> allAnnotations;

    /** The annotation insertions seen so far. */
    public List<Insertion> insertions;
    /** A printer for annotations. */
    private DefaultPrettyPrinter printer;
    /** The lines of the String representation of the second AST. */
    private List<String> lines;
    /** The line separator used in the text the second AST was parsed from */
    private String lineSeparator;
    /**
     * Stores the offsets of the lines in the string representation of the second AST. At index i,
     * stores the number of characters from the start of the file to the beginning of the ith line.
     */
    private List<Integer> cumulativeLineSizes;

    /**
     * Constructs a {@code BuildInsertionsVisitor} where {@code destFileContents} is the String
     * representation of the AST to insert annotation into, that uses the given line separator. When
     * visiting a node pair, the second node must always be from an AST generated from this String.
     *
     * @param destFileContents the String the second vistide AST was parsed from
     * @param lineSeparator the line separator that {@code destFileContents} uses
     */
    public BuildInsertionsVisitor(String destFileContents, String lineSeparator) {
      allAnnotations = null;
      insertions = new ArrayList<>();
      printer = new DefaultPrettyPrinter();
      String[] lines = destFileContents.split(lineSeparator);
      this.lines = Arrays.asList(lines);
      this.lineSeparator = lineSeparator;
      cumulativeLineSizes = new ArrayList<>();
      cumulativeLineSizes.add(0);
      for (int i = 1; i < lines.length; i++) {
        int lastSize = cumulativeLineSizes.get(i - 1);
        int lastLineLength = lines[i - 1].length() + lineSeparator.length();
        cumulativeLineSizes.add(lastSize + lastLineLength);
      }
    }

    @Override
    public void defaultAction(Node src, Node dest) {
      if (!(src instanceof NodeWithAnnotations<?>)) {
        return;
      }
      NodeWithAnnotations<?> srcWithAnnos = (NodeWithAnnotations<?>) src;

      // If `src` is a declaration, its annotations are declaration annotations.
      if (src instanceof MethodDeclaration) {
        addAnnotationOnOwnLine(dest.getBegin().get(), srcWithAnnos.getAnnotations());
        return;
      } else if (src instanceof FieldDeclaration) {
        addAnnotationOnOwnLine(dest.getBegin().get(), srcWithAnnos.getAnnotations());
        return;
      }

      // `src`'s annotations are type annotations.
      Position position;
      if (dest instanceof ClassOrInterfaceType) {
        // In a multi-part name like my.package.MyClass, type annotations go directly in front of
        // MyClass instead of the full name.
        position = ((ClassOrInterfaceType) dest).getName().getBegin().get();
      } else {
        position = dest.getBegin().get();
      }
      addAnnotations(position, srcWithAnnos.getAnnotations(), 0, false);
    }

    @Override
    public void visit(ArrayType src, Node other) {
      ArrayType dest = (ArrayType) other;
      // The second component of this pair contains a list of ArrayBracketPairs from left to
      // right. For example, if src contains String[][], then the list will contain the
      // types String[] and String[][]. To insert array annotations in the correct location,
      // we insert them directly to the right of the end of the previous element.
      Pair<Type, List<ArrayType.ArrayBracketPair>> srcArrayTypes = ArrayType.unwrapArrayTypes(src);
      Pair<Type, List<ArrayType.ArrayBracketPair>> destArrayTypes =
          ArrayType.unwrapArrayTypes(dest);
      // The first annotations go directly after the element type.
      Position firstPosition = destArrayTypes.a.getEnd().get();
      addAnnotations(firstPosition, srcArrayTypes.b.get(0).getAnnotations(), 1, false);
      for (int i = 1; i < srcArrayTypes.b.size(); i++) {
        Position position = destArrayTypes.b.get(i - 1).getTokenRange().get().toRange().get().end;
        addAnnotations(position, srcArrayTypes.b.get(i).getAnnotations(), 1, true);
      }

      // Visit the component type.
      srcArrayTypes.a.accept(this, destArrayTypes.a);
    }

    @Override
    public void visit(CompilationUnit src, Node other) {
      CompilationUnit dest = (CompilationUnit) other;
      defaultAction(src, dest);

      // Gather annotations used in the ajava file.
      allAnnotations = getImportedAnnotations(src);

      // Move any annotations that JavaParser puts in the declaration position but belong only in
      // the type position.
      src.accept(new TypeAnnotationMover(allAnnotations, elements), null);

      // Transfer import statements from the ajava file to the Java file.

      List<String> newImports;
      { // set `newImports`
        Set<String> existingImports = new HashSet<>();
        for (ImportDeclaration importDecl : dest.getImports()) {
          existingImports.add(printer.print(importDecl));
        }

        newImports = new ArrayList<>();
        for (ImportDeclaration importDecl : src.getImports()) {
          String importString = printer.print(importDecl);
          if (!existingImports.contains(importString)) {
            newImports.add(importString);
          }
        }
      }

      if (!newImports.isEmpty()) {
        int position;
        int lineBreaksBeforeFirstImport;
        if (!dest.getImports().isEmpty()) {
          Position lastImportPosition =
              dest.getImports().get(dest.getImports().size() - 1).getEnd().get();
          position = getFilePosition(lastImportPosition) + 1;
          lineBreaksBeforeFirstImport = 1;
        } else if (dest.getPackageDeclaration().isPresent()) {
          Position packagePosition = dest.getPackageDeclaration().get().getEnd().get();
          position = getFilePosition(packagePosition) + 1;
          lineBreaksBeforeFirstImport = 2;
        } else {
          position = 0;
          lineBreaksBeforeFirstImport = 0;
        }

        String insertionContent = "";
        // In Java 11, use String::repeat.
        for (int i = 0; i < lineBreaksBeforeFirstImport; i++) {
          insertionContent += lineSeparator;
        }
        insertionContent += String.join("", newImports);

        insertions.add(new Insertion(position, insertionContent));
      }

      src.getModule().ifPresent(l -> l.accept(this, dest.getModule().get()));
      src.getPackageDeclaration()
          .ifPresent(l -> l.accept(this, dest.getPackageDeclaration().get()));
      for (int i = 0; i < src.getTypes().size(); i++) {
        src.getTypes().get(i).accept(this, dest.getTypes().get(i));
      }
    }

    /**
     * Creates an insertion for a collection of annotations and adds it to {@link #insertions}. The
     * annotations will appear on their own line (unless any non-whitespace characters precede the
     * insertion position on its own line).
     *
     * @param position the position of the insertion
     * @param annotations List of annotations to insert
     */
    private void addAnnotationOnOwnLine(Position position, List<AnnotationExpr> annotations) {
      String line = lines.get(position.line - 1);
      int insertionColumn = position.column - 1;
      boolean ownLine = true;
      for (int i = 0; i < insertionColumn; i++) {
        if (line.charAt(i) != ' ' && line.charAt(i) != '\t') {
          ownLine = false;
          break;
        }
      }

      if (ownLine) {
        StringJoiner insertionContent = new StringJoiner(" ");
        for (AnnotationExpr annotation : annotations) {
          insertionContent.add(printer.print(annotation));
        }

        if (insertionContent.length() == 0) {
          return;
        }

        String leadingWhitespace = line.substring(0, insertionColumn);
        int filePosition = getFilePosition(position);
        insertions.add(
            new Insertion(
                filePosition,
                insertionContent.toString() + lineSeparator + leadingWhitespace,
                true));
      } else {
        addAnnotations(position, annotations, 0, false);
      }
    }

    /**
     * Creates an insertion for a collection of annotations at {@code position} + {@code offset} and
     * adds it to {@link #insertions}.
     *
     * @param position the position of the insertion
     * @param annotations List of annotations to insert
     * @param offset additional offset of the insertion after {@code position}
     * @param addSpaceBefore if true, the insertion content will start with a space
     */
    private void addAnnotations(
        Position position,
        Iterable<AnnotationExpr> annotations,
        int offset,
        boolean addSpaceBefore) {
      StringBuilder insertionContent = new StringBuilder();
      for (AnnotationExpr annotation : annotations) {
        insertionContent.append(printer.print(annotation));
        insertionContent.append(" ");
      }

      // Can't test `annotations.isEmpty()` earlier because `annotations` has type `Iterable`.
      if (insertionContent.length() == 0) {
        return;
      }

      if (addSpaceBefore) {
        insertionContent.insert(0, " ");
      }

      int filePosition = getFilePosition(position) + offset;
      insertions.add(new Insertion(filePosition, insertionContent.toString()));
    }

    /**
     * Converts a Position (which contains a line and column) to an offset from the start of the
     * file, in characters.
     *
     * @param position a Position
     * @return the total offset of the position from the start of the file
     */
    private int getFilePosition(Position position) {
      return cumulativeLineSizes.get(position.line - 1) + (position.column - 1);
    }
  }

  /**
   * Returns all annotations imported by the annotation file as a mapping from simple and qualified
   * names to TypeElements.
   *
   * @param cu compilation unit to extract imports from
   * @return a map from names to TypeElement, for all annotations imported by the annotation file.
   *     Two entries for each annotation: one for the simple name and another for the
   *     fully-qualified name, with the same value.
   */
  private Map<String, TypeElement> getImportedAnnotations(CompilationUnit cu) {
    if (cu.getImports() == null) {
      return Collections.emptyMap();
    }

    Map<String, TypeElement> result = new HashMap<>();
    for (ImportDeclaration importDecl : cu.getImports()) {
      if (importDecl.isAsterisk()) {
        @SuppressWarnings("signature" // https://tinyurl.com/cfissue/3094:
        // com.github.javaparser.ast.expr.Name inherits toString,
        // so there can be no annotation for it
        )
        @DotSeparatedIdentifiers String imported = importDecl.getName().toString();
        if (importDecl.isStatic()) {
          // Wildcard import of members of a type (class or interface)
          TypeElement element = elements.getTypeElement(imported);
          if (element != null) {
            // Find nested annotations
            result.putAll(AnnotationFileParser.annosInType(element));
          }

        } else {
          // Wildcard import of members of a package
          PackageElement element = elements.getPackageElement(imported);
          if (element != null) {
            result.putAll(AnnotationFileParser.annosInPackage(element));
          }
        }
      } else {
        @SuppressWarnings("signature" // importDecl is non-wildcard, so its name is
        // @FullyQualifiedName
        )
        @FullyQualifiedName String imported = importDecl.getNameAsString();
        TypeElement importType = elements.getTypeElement(imported);
        if (importType != null && importType.getKind() == ElementKind.ANNOTATION_TYPE) {
          TypeElement annoElt = elements.getTypeElement(imported);
          if (annoElt != null) {
            result.put(annoElt.getSimpleName().toString(), annoElt);
          }
        }
      }
    }
    return result;
  }

  /**
   * Inserts all annotations from the ajava file read from {@code annotationFile} into a Java file
   * with contents {@code javaFileContents} that uses the given line separator and returns the
   * resulting String.
   *
   * @param annotationFile input stream for an ajava file for {@code javaFileContents}
   * @param javaFileContents contents of a Java file to insert annotations into
   * @param lineSeparator the line separator {@code javaFileContents} uses
   * @return a modified {@code javaFileContents} with annotations from {@code annotationFile}
   *     inserted
   */
  public String insertAnnotations(
      InputStream annotationFile, String javaFileContents, String lineSeparator) {
    CompilationUnit annotationCu = JavaParserUtil.parseCompilationUnit(annotationFile);
    CompilationUnit javaCu = JavaParserUtil.parseCompilationUnit(javaFileContents);
    BuildInsertionsVisitor insertionVisitor =
        new BuildInsertionsVisitor(javaFileContents, lineSeparator);
    annotationCu.accept(insertionVisitor, javaCu);
    List<Insertion> insertions = insertionVisitor.insertions;
    insertions.sort(InsertAjavaAnnotations::compareInsertions);

    StringBuilder result = new StringBuilder(javaFileContents);
    for (Insertion insertion : insertions) {
      result.insert(insertion.position, insertion.contents);
    }
    return result.toString();
  }

  /**
   * Compares two insertions in the reverse order of where their content should appear in the file.
   * Making an insertion changes the offset values of all content after the insertion, so performing
   * the insertions in reverse order of appearance removes the need to recalculate the positions of
   * other insertions.
   *
   * <p>The order in which insertions should appear is determined first by their absolute position
   * in the file, and second by whether they have their own line. In a method like
   * {@code @Pure @Tainting String myMethod()} both annotations should be inserted at the same
   * location (right before "String"), but {@code @Pure} should always come first because it belongs
   * on its own line.
   *
   * @param insertion1 the first insertion
   * @param insertion2 the second insertion
   * @return a negative integer, zero, or a positive integer if {@code insertion1} belongs before,
   *     at the same position, or after {@code insertion2} respectively in the above ordering
   */
  private static int compareInsertions(Insertion insertion1, Insertion insertion2) {
    int cmp = Integer.compare(insertion1.position, insertion2.position);
    if (cmp == 0 && (insertion1.ownLine != insertion2.ownLine)) {
      if (insertion1.ownLine) {
        cmp = -1;
      } else {
        cmp = 1;
      }
    }

    return -cmp;
  }

  /**
   * Inserts all annotations from the ajava file at {@code annotationFilePath} into {@code
   * javaFilePath}.
   *
   * @param annotationFilePath path to an ajava file
   * @param javaFilePath path to a Java file to insert annotation into
   */
  public void insertAnnotations(String annotationFilePath, String javaFilePath) {
    try {
      File javaFile = new File(javaFilePath);
      String fileContents = FilesPlume.readFile(javaFile);
      String lineSeparator = FilesPlume.inferLineSeparator(annotationFilePath);
      FileInputStream annotationInputStream = new FileInputStream(annotationFilePath);
      String result = insertAnnotations(annotationInputStream, fileContents, lineSeparator);
      annotationInputStream.close();
      FilesPlume.writeFile(javaFile, result);
    } catch (IOException e) {
      System.err.println(
          "Failed to insert annotations from file "
              + annotationFilePath
              + " into file "
              + javaFilePath);
      System.exit(1);
    }
  }

  /**
   * Inserts annotations from ajava files into Java files in place.
   *
   * <p>The first argument is an ajava file or a directory containing ajava files.
   *
   * <p>The second argument is a Java file or a directory containing Java files to insert
   * annotations into.
   *
   * <p>For each Java file, checks if any ajava files from the first argument match it. For each
   * such ajava file, inserts all its annotations into the Java file.
   *
   * @param args command line arguments: the first element should be a path to ajava files and the
   *     second should be the directory containing Java files to insert into
   */
  public static void main(String[] args) {
    if (args.length != 2) {
      System.out.println(
          "Usage: java InsertAjavaAnnotations <ajava-file-or-directory> <java-file-or-directory");
      System.exit(1);
    }

    String ajavaDir = args[0];
    String javaSourceDir = args[1];
    AnnotationFileStore annotationFiles = new AnnotationFileStore();
    annotationFiles.addFileOrDirectory(new File(ajavaDir));
    InsertAjavaAnnotations inserter = new InsertAjavaAnnotations(createElements());
    // For each Java file, this visitor inserts annotations into it.
    FileVisitor<Path> insertionVisitor =
        new SimpleFileVisitor<Path>() {
          @Override
          public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
            if (!path.getFileName().toString().endsWith(".java")) {
              return FileVisitResult.CONTINUE;
            }

            CompilationUnit root = null;
            try {
              root = JavaParserUtil.parseCompilationUnit(path.toFile());
            } catch (IOException e) {
              System.err.println("Failed to read file: " + path);
              System.exit(1);
            }

            Set<String> annotationFilesForRoot = new LinkedHashSet<>();
            for (TypeDeclaration<?> type : root.getTypes()) {
              String name = JavaParserUtil.getFullyQualifiedName(type, root);
              annotationFilesForRoot.addAll(annotationFiles.getAnnotationFileForType(name));
            }

            for (String annotationFile : annotationFilesForRoot) {
              inserter.insertAnnotations(annotationFile, path.toString());
            }

            return FileVisitResult.CONTINUE;
          }
        };

    try {
      Files.walkFileTree(Paths.get(javaSourceDir), insertionVisitor);
    } catch (IOException e) {
      System.out.println("Error while adding annotations to: " + javaSourceDir);
      e.printStackTrace();
      System.exit(1);
    }
  }
}
