package org.checkerframework.framework.test.diagnostics;

import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.javacutil.Pair;
import org.plumelib.util.CollectionsPlume;

/** A set of utilities and factory methods useful for working with TestDiagnostics. */
public class TestDiagnosticUtils {

  /** How the diagnostics appear in Java source files. */
  public static final String DIAGNOSTIC_IN_JAVA_REGEX =
      "\\s*(error|fixable-error|warning|fixable-warning|other):\\s*(\\(?.*\\)?)\\s*";
  /** How the diagnostics appear in Java source files. */
  public static final Pattern DIAGNOSTIC_IN_JAVA_PATTERN =
      Pattern.compile(DIAGNOSTIC_IN_JAVA_REGEX);

  public static final String DIAGNOSTIC_WARNING_IN_JAVA_REGEX = "\\s*warning:\\s*(.*\\s*.*)\\s*";
  public static final Pattern DIAGNOSTIC_WARNING_IN_JAVA_PATTERN =
      Pattern.compile(DIAGNOSTIC_WARNING_IN_JAVA_REGEX);

  // How the diagnostics appear in javax tools diagnostics from the compiler.
  public static final String DIAGNOSTIC_REGEX = ":(\\d+):" + DIAGNOSTIC_IN_JAVA_REGEX;
  public static final Pattern DIAGNOSTIC_PATTERN = Pattern.compile(DIAGNOSTIC_REGEX);

  public static final String DIAGNOSTIC_WARNING_REGEX =
      ":(\\d+):" + DIAGNOSTIC_WARNING_IN_JAVA_REGEX;
  public static final Pattern DIAGNOSTIC_WARNING_PATTERN =
      Pattern.compile(DIAGNOSTIC_WARNING_REGEX);

  // How the diagnostics appear in diagnostic files (.out).
  public static final String DIAGNOSTIC_FILE_REGEX = ".+\\.java" + DIAGNOSTIC_REGEX;
  public static final Pattern DIAGNOSTIC_FILE_PATTERN = Pattern.compile(DIAGNOSTIC_FILE_REGEX);

  public static final String DIAGNOSTIC_FILE_WARNING_REGEX = ".+\\.java" + DIAGNOSTIC_WARNING_REGEX;
  public static final Pattern DIAGNOSTIC_FILE_WARNING_PATTERN =
      Pattern.compile(DIAGNOSTIC_FILE_WARNING_REGEX);

  /**
   * Instantiate the diagnostic based on a string that would appear in diagnostic files (i.e. files
   * that only contain line after line of expected diagnostics).
   *
   * @param stringFromDiagnosticFile a single diagnostic string to parse
   * @return a new TestDiagnostic
   */
  public static TestDiagnostic fromDiagnosticFileString(String stringFromDiagnosticFile) {
    return fromPatternMatching(
        DIAGNOSTIC_FILE_PATTERN,
        DIAGNOSTIC_WARNING_IN_JAVA_PATTERN,
        "",
        null,
        stringFromDiagnosticFile);
  }

  /**
   * Instantiate the diagnostic from a string that would appear in a Java file, e.g.: "error:
   * (message)"
   *
   * @param filename the file containing the diagnostic (and the error)
   * @param lineNumber the line number of the line immediately below the diagnostic comment in the
   *     Java file
   * @param stringFromJavaFile the string containing the diagnostic
   * @return a new TestDiagnostic
   */
  public static TestDiagnostic fromJavaFileComment(
      String filename, long lineNumber, String stringFromJavaFile) {
    return fromPatternMatching(
        DIAGNOSTIC_IN_JAVA_PATTERN,
        DIAGNOSTIC_WARNING_IN_JAVA_PATTERN,
        filename,
        lineNumber,
        stringFromJavaFile);
  }
  /**
   * Instantiate a diagnostic from output produced by the Java compiler. The resulting diagnostic is
   * never fixable and always has parentheses.
   */
  public static TestDiagnostic fromJavaxToolsDiagnostic(
      String diagnosticString, boolean noMsgText) {
    // It would be nice not to parse this from the diagnostic string.
    // However, diagnostic.toString() may contain "[unchecked]" even though getMessage() does not.
    // Since we want to match the error messages reported by javac exactly, we must parse.
    Pair<String, String> trimmed = formatJavaxToolString(diagnosticString, noMsgText);
    return fromPatternMatching(
        DIAGNOSTIC_PATTERN, DIAGNOSTIC_WARNING_PATTERN, trimmed.second, null, trimmed.first);
  }

  /**
   * Instantiate the diagnostic from a JSpecify string that would appear in a Java file, e.g.:
   * "jspecify_some_category".
   *
   * @param filename the file containing the diagnostic (and the error)
   * @param lineNumber the line number of the line immediately below the diagnostic comment in the
   *     Java file
   * @param stringFromJavaFile the string containing the diagnostic
   * @return a new TestDiagnostic
   */
  public static TestDiagnostic fromJSpecifyFileComment(
      String filename, long lineNumber, String stringFromJavaFile) {
    return new TestDiagnostic(
        filename,
        lineNumber,
        DiagnosticKind.JSpecify,
        stringFromJavaFile,
        /*isFixable=*/ false,
        /*omitParentheses=*/ true);
  }

  /**
   * Instantiate the diagnostic via pattern-matching against patterns.
   *
   * @param diagnosticPattern a pattern that matches any diagnostic
   * @param warningPattern a pattern that matches a warning diagnostic
   * @param filename the file name
   * @param lineNumber the line number
   * @param diagnosticString the string to parse
   * @return a diagnostic parsed from the given string
   */
  @SuppressWarnings("nullness") // TODO: regular expression group access
  protected static TestDiagnostic fromPatternMatching(
      Pattern diagnosticPattern,
      Pattern warningPattern,
      String filename,
      @Nullable Long lineNumber,
      String diagnosticString) {
    final DiagnosticKind kind;
    final String message;
    final boolean isFixable;
    final boolean noParentheses;
    long lineNo = -1;
    int capturingGroupOffset = 1;

    if (lineNumber != null) {
      lineNo = lineNumber;
      capturingGroupOffset = 0;
    }

    Matcher diagnosticMatcher = diagnosticPattern.matcher(diagnosticString);
    if (diagnosticMatcher.matches()) {
      Pair<DiagnosticKind, Boolean> categoryToFixable =
          parseCategoryString(diagnosticMatcher.group(1 + capturingGroupOffset));
      kind = categoryToFixable.first;
      isFixable = categoryToFixable.second;
      String msg = diagnosticMatcher.group(2 + capturingGroupOffset).trim();
      noParentheses = msg.equals("") || msg.charAt(0) != '(' || msg.charAt(msg.length() - 1) != ')';
      message = noParentheses ? msg : msg.substring(1, msg.length() - 1);

      if (lineNumber == null) {
        lineNo = Long.parseLong(diagnosticMatcher.group(1));
      }

    } else {
      Matcher warningMatcher = warningPattern.matcher(diagnosticString);
      if (warningMatcher.matches()) {
        kind = DiagnosticKind.Warning;
        isFixable = false;
        message = warningMatcher.group(1 + capturingGroupOffset);
        noParentheses = true;

        if (lineNumber == null) {
          lineNo = Long.parseLong(diagnosticMatcher.group(1));
        }

      } else if (diagnosticString.startsWith("warning:")) {
        kind = DiagnosticKind.Warning;
        isFixable = false;
        message = diagnosticString.substring("warning:".length()).trim();
        noParentheses = true;
        if (lineNumber != null) {
          lineNo = lineNumber;
        } else {
          lineNo = 0;
        }

      } else {
        kind = DiagnosticKind.Other;
        isFixable = false;
        message = diagnosticString;
        noParentheses = true;

        // this should only happen if we are parsing a Java Diagnostic from the compiler
        // that we did do not handle
        if (lineNumber == null) {
          lineNo = -1;
        }
      }
    }
    return new TestDiagnostic(filename, lineNo, kind, message, isFixable, noParentheses);
  }

  /**
   * Given a javax diagnostic, return a pair of (trimmed, fileame), where "trimmed" is the first
   * line of the message, without the leading filename.
   *
   * @param original a javax diagnostic
   * @param noMsgText whether to do work; if false, this returns a pair of (argument, "").
   * @return the diagnostic, split into message and filename
   */
  public static Pair<String, String> formatJavaxToolString(String original, boolean noMsgText) {
    String trimmed = original;
    String filename = "";
    if (noMsgText) {
      if (!retainAllLines(trimmed)) {
        int lineSepPos = trimmed.indexOf(System.lineSeparator());
        if (lineSepPos != -1) {
          trimmed = trimmed.substring(0, lineSepPos);
        }

        int extensionPos = trimmed.indexOf(".java:");
        if (extensionPos != -1) {
          int basenameStart = trimmed.lastIndexOf(File.separator);
          filename = trimmed.substring(basenameStart + 1, extensionPos + 5).trim();
          trimmed = trimmed.substring(extensionPos + 5).trim();
        }
      }
    }

    return Pair.of(trimmed, filename);
  }

  /**
   * Returns true if all lines of the message should be shown, false if only the first line should
   * be shown.
   *
   * @param message a diagnostic message
   * @return true if all lines of the message should be shown
   */
  private static boolean retainAllLines(String message) {
    // Retain all if it is a thrown exception "unexpected Throwable" or it is a Checker Framework
    // Error (contains "Compilation unit") or is OutOfMemoryError.
    return message.contains("unexpected Throwable")
        || message.contains("Compilation unit")
        || message.contains("OutOfMemoryError");
  }

  /**
   * Given a category string that may be prepended with "fixable-", return the category enum that
   * corresponds with the category and whether or not it is a isFixable error
   */
  private static Pair<DiagnosticKind, Boolean> parseCategoryString(String category) {
    final String fixable = "fixable-";
    final boolean isFixable = category.startsWith(fixable);
    if (isFixable) {
      category = category.substring(fixable.length());
    }
    DiagnosticKind categoryEnum = DiagnosticKind.fromParseString(category);
    if (categoryEnum == null) {
      throw new Error("Unparsable category: " + category);
    }

    return Pair.of(categoryEnum, isFixable);
  }

  /**
   * Return true if this line in a Java file indicates an expected diagnostic that might be
   * continued on the next line.
   */
  public static boolean isJavaDiagnosticLineStart(String originalLine) {
    final String trimmedLine = originalLine.trim();
    return trimmedLine.startsWith("// ::") || trimmedLine.startsWith("// warning:");
  }

  /**
   * Convert an end-of-line diagnostic message to a beginning-of-line one. Returns the argument
   * unchanged if it does not contain an end-of-line diagnostic message.
   *
   * <p>Most diagnostics in Java files start at the beginning of a line. Occasionally, javac issues
   * a warning about implicit code, such as an implicit constructor, on the line <em>immediately
   * after</em> a curly brace. The only place to put the expected diagnostic message is on the line
   * with the curly brace.
   *
   * <p>This implementation replaces "{ // ::" by "// ::", converting the end-of-line diagnostic
   * message to a beginning-of-line one that the rest of the code can handle. It is rather specific
   * (to avoid false positive matches, such as when "// ::" is commented out in source code). It
   * could be extended in the future if such an extension is necessary.
   */
  public static String handleEndOfLineJavaDiagnostic(String originalLine) {
    int curlyIndex = originalLine.indexOf("{ // ::");
    if (curlyIndex == -1) {
      return originalLine;
    } else {
      return originalLine.substring(curlyIndex + 2);
    }
  }

  /** Return true if this line in a Java file continues an expected diagnostic. */
  @EnsuresNonNullIf(result = true, expression = "#1")
  public static boolean isJavaDiagnosticLineContinuation(@Nullable String originalLine) {
    if (originalLine == null) {
      return false;
    }
    final String trimmedLine = originalLine.trim();
    // Unlike with errors, there is no logic elsewhere for splitting multiple "warning:"s.  So,
    // avoid concatenating them.  Also, each one must begin a line.  They are allowed to wrap to
    // the next line, though.
    return trimmedLine.startsWith("// ") && !trimmedLine.startsWith("// warning:");
  }

  /**
   * Return the continuation part. The argument is such that {@link
   * #isJavaDiagnosticLineContinuation} returns true.
   */
  public static String continuationPart(String originalLine) {
    return originalLine.trim().substring(2).trim();
  }

  /**
   * Convert a line in a Java source file to a TestDiagnosticLine.
   *
   * <p>The input {@code line} is possibly the concatenation of multiple source lines, if the
   * diagnostic was split across lines in the source code.
   */
  public static TestDiagnosticLine fromJavaSourceLine(
      String filename, String line, long lineNumber) {
    final String trimmedLine = line.trim();
    long errorLine = lineNumber + 1;

    if (trimmedLine.startsWith("// ::")) {
      String restOfLine = trimmedLine.substring(5); // drop the "// ::"
      String[] diagnosticStrs = restOfLine.split("::");
      List<TestDiagnostic> diagnostics =
          CollectionsPlume.mapList(
              (String diagnostic) -> fromJavaFileComment(filename, errorLine, diagnostic),
              diagnosticStrs);
      return new TestDiagnosticLine(
          filename, errorLine, line, Collections.unmodifiableList(diagnostics));

    } else if (trimmedLine.startsWith("// warning:")) {
      // This special diagnostic does not expect a line number nor a file name
      String diagnosticString = trimmedLine.substring(2);
      TestDiagnostic diagnostic = fromJavaFileComment("", 0, diagnosticString);
      return new TestDiagnosticLine("", 0, line, Collections.singletonList(diagnostic));
    } else if (trimmedLine.startsWith("//::")) {
      TestDiagnostic diagnostic =
          new TestDiagnostic(
              filename,
              lineNumber,
              DiagnosticKind.Error,
              "Use \"// ::\", not \"//::\"",
              false,
              true);
      return new TestDiagnosticLine(
          filename, lineNumber, line, Collections.singletonList(diagnostic));
    } else if (trimmedLine.startsWith("// jspecify_")) {
      TestDiagnostic diagnostic =
          fromJSpecifyFileComment(filename, errorLine, trimmedLine.substring(3));
      return new TestDiagnosticLine(
          filename, errorLine, line, Collections.singletonList(diagnostic));
    } else {
      // It's a bit gross to create empty diagnostics (returning null might be more
      // efficient), but they will be filtered out later.
      return new TestDiagnosticLine(filename, errorLine, line, Collections.emptyList());
    }
  }

  /** Convert a line in a DiagnosticFile to a TestDiagnosticLine. */
  public static TestDiagnosticLine fromDiagnosticFileLine(String diagnosticLine) {
    final String trimmedLine = diagnosticLine.trim();
    if (trimmedLine.startsWith("#") || trimmedLine.isEmpty()) {
      return new TestDiagnosticLine("", -1, diagnosticLine, Collections.emptyList());
    }

    TestDiagnostic diagnostic = fromDiagnosticFileString(diagnosticLine);
    return new TestDiagnosticLine(
        "", diagnostic.getLineNumber(), diagnosticLine, Arrays.asList(diagnostic));
  }

  public static Set<TestDiagnostic> fromJavaxDiagnosticList(
      List<Diagnostic<? extends JavaFileObject>> javaxDiagnostics, boolean noMsgText) {
    Set<TestDiagnostic> diagnostics = new LinkedHashSet<>(javaxDiagnostics.size());

    for (Diagnostic<? extends JavaFileObject> diagnostic : javaxDiagnostics) {
      // See TestDiagnosticUtils as to why we use diagnostic.toString rather
      // than convert from the diagnostic itself
      final String diagnosticString = diagnostic.toString();

      // suppress Xlint warnings
      if (diagnosticString.contains("uses unchecked or unsafe operations.")
          || diagnosticString.contains("Recompile with -Xlint:unchecked for details.")
          || diagnosticString.endsWith(" declares unsafe vararg methods.")
          || diagnosticString.contains("Recompile with -Xlint:varargs for details.")) {
        continue;
      }

      diagnostics.add(TestDiagnosticUtils.fromJavaxToolsDiagnostic(diagnosticString, noMsgText));
    }

    return diagnostics;
  }

  /**
   * Converts the given diagnostics to strings (as they would appear in a source file individually).
   *
   * @param diagnostics a list of diagnostics
   * @return a list of the diagnastics as they would appear in a source file
   */
  public static List<String> diagnosticsToString(List<TestDiagnostic> diagnostics) {
    return CollectionsPlume.mapList(TestDiagnostic::toString, diagnostics);
  }

  public static void removeDiagnosticsOfKind(
      DiagnosticKind kind, List<TestDiagnostic> expectedDiagnostics) {
    for (int i = 0; i < expectedDiagnostics.size(); /*no-increment*/ ) {
      if (expectedDiagnostics.get(i).getKind() == kind) {
        expectedDiagnostics.remove(i);
      } else {
        ++i;
      }
    }
  }
}
