// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.googlesource.gerrit.plugins.copyright;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.common.hash.Hashing;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.gerrit.server.git.validators.ValidationMessage;
import com.googlesource.gerrit.plugins.copyright.lib.IndexedLineReader;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;

/**
 * Utility for verifying copyright plugin configurations.
 *
 * <p>{@code main} implements a command-line tool for measuring performance against a large test
 * file constructed to trigger excessive backtracking.
 */
public class CheckConfig {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static final String toolName = "check_new_config";

  private static final String ACCESS = "access";
  private static final String LABEL = "label";
  private static final String PLUGIN = "plugin";
  private static final int BUFFER_SIZE = 2048;
  private static final char[] BUFFER = new char[BUFFER_SIZE];

  private String pluginName;
  private Config configProject;
  ScannerConfig scannerConfig;

  public CheckConfig(String pluginName, String projectConfigContents)
      throws ConfigInvalidException {
    this.pluginName = pluginName;

    configProject = new Config();
    configProject.fromText(projectConfigContents);
    Config config = new Config();
    for (String name : configProject.getNames(PLUGIN, pluginName)) {
      config.setStringList(
          PLUGIN,
          pluginName,
          name,
          Arrays.asList(configProject.getStringList(PLUGIN, pluginName, name)));
    }
    PluginConfig pluginConfig = new PluginConfig(pluginName, config);
    this.scannerConfig = new ScannerConfig(pluginName);
    this.scannerConfig.readConfigFile(pluginConfig);
  }

  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (other == null) {
      return false;
    }
    if (other instanceof CheckConfig) {
      CheckConfig that = (CheckConfig) other;
      return Objects.equals(this.pluginName, that.pluginName)
          && Objects.equals(this.scannerConfig, that.scannerConfig);
    }
    return false;
  }

  @Override
  public int hashCode() {
    return Objects.hash(pluginName, scannerConfig);
  }

  /**
   * Validates the final state of {@code trialConfig}.
   *
   * <p>Uses {@code reviewApi}, when given, to verify account information. When {@code
   * pluginEnabled} is false, treats errors as warnings.
   */
  public static void checkProjectConfig(
      CopyrightReviewApi reviewApi, boolean pluginEnabled, CheckConfig trialConfig) {
    CurrentUser fromUser =
        reviewApi == null
            ? null
            : reviewApi.getSendingUser(trialConfig.scannerConfig.fromAccountId);
    if (Strings.nullToEmpty(trialConfig.scannerConfig.reviewLabel).trim().isEmpty()) {
      trialConfig.scannerConfig.messages.add(
          new CommitValidationMessage(
              trialConfig.scannerConfig.pluginKeyRequired(
                  ScannerConfig.KEY_REVIEW_LABEL,
                  "please use \""
                      + ScannerConfig.KEY_REVIEW_LABEL
                      + " = <label name>\" to identify the label "
                      + (trialConfig.scannerConfig.fromAccountId < 1 || fromUser == null
                          ? "the plugin"
                          : fromUser.getLoggableName())
                      + " will vote on"),
              pluginEnabled ? ValidationMessage.Type.ERROR : ValidationMessage.Type.WARNING));
    } else {
      String labelName = trialConfig.scannerConfig.reviewLabel.trim();
      if (!trialConfig.configProject.getSubsections(LABEL).contains(labelName)) {
        trialConfig.scannerConfig.messages.add(
            new CommitValidationMessage(
                trialConfig.scannerConfig.pluginKeyValueMessage(
                    ScannerConfig.KEY_REVIEW_LABEL,
                    labelName,
                    "no [" + LABEL + " \"" + labelName + "\"] section configured."),
                pluginEnabled ? ValidationMessage.Type.ERROR : ValidationMessage.Type.WARNING));
      }
      String[] voters =
          trialConfig.configProject.getStringList(
              ACCESS, RefNames.REFS_HEADS + "*", "label-" + labelName);
      boolean foundApprover = false;
      for (String voter : voters) {
        if (voter.trim().split("\\s", 2)[0].endsWith("+2")) {
          foundApprover = true;
          break;
        }
      }
      if (!foundApprover) {
        trialConfig.scannerConfig.messages.add(
            new CommitValidationMessage(
                trialConfig.scannerConfig.pluginKeyValueMessage(
                    ScannerConfig.KEY_REVIEW_LABEL,
                    labelName,
                    "no configured approvers for "
                        + labelName
                        + " on "
                        + RefNames.REFS_HEADS
                        + "*"),
                pluginEnabled ? ValidationMessage.Type.ERROR : ValidationMessage.Type.WARNING));
      }
      voters =
          trialConfig.configProject.getStringList(
              ACCESS, RefNames.REFS_CONFIG, "label-" + labelName);
      foundApprover = false;
      for (String voter : voters) {
        if (voter.trim().split("\\s", 2)[0].endsWith("+2")) {
          foundApprover = true;
          break;
        }
      }
      if (!foundApprover) {
        trialConfig.scannerConfig.messages.add(
            new CommitValidationMessage(
                trialConfig.scannerConfig.pluginKeyValueMessage(
                    ScannerConfig.KEY_REVIEW_LABEL,
                    labelName,
                    "no configured approvers for " + labelName + " on " + RefNames.REFS_CONFIG),
                pluginEnabled ? ValidationMessage.Type.ERROR : ValidationMessage.Type.WARNING));
      }
    }
    if (trialConfig.scannerConfig.reviewers.isEmpty()) {
      trialConfig.scannerConfig.messages.add(
          ScannerConfig.warningMessage(
              trialConfig.scannerConfig.pluginKeyRequired(
                  ScannerConfig.KEY_REVIEWER, "adding no qualified reviewer may cause confusion")));
    }
    if (trialConfig.scannerConfig.fromAccountId < 1) {
      trialConfig.scannerConfig.messages.add(
          new CommitValidationMessage(
              trialConfig.scannerConfig.pluginKeyRequired(
                  ScannerConfig.KEY_FROM,
                  "please use \""
                      + ScannerConfig.KEY_FROM
                      + " = <account id>\" to identify a"
                      + " non-interactive user with full voting permissions for the review label '"
                      + trialConfig.scannerConfig.reviewLabel
                      + "'"),
              pluginEnabled ? ValidationMessage.Type.ERROR : ValidationMessage.Type.WARNING));
      // TODO: inject ReviewerAdder into reviewApi, and use ReviewerAdder.prepare
      //       a la
      // https://gerrit.googlesource.com/gerrit/+/refs/heads/master/java/com/google/gerrit/server/restapi/change/PostReview.java#265
      //       to verify the reviewers and ccs are valid.
    }
    if (fromUser != null && fromUser instanceof IdentifiedUser) {
      IdentifiedUser sendingUser = (IdentifiedUser) fromUser;
      Account account = sendingUser.getAccount();
      if (Strings.isNullOrEmpty(account.getFullName())
          && Strings.isNullOrEmpty(account.getPreferredEmail())) {
        trialConfig.scannerConfig.messages.add(
            ScannerConfig.warningMessage(
                trialConfig.scannerConfig.pluginKeyValueMessage(
                    ScannerConfig.KEY_FROM,
                    Long.toString(trialConfig.scannerConfig.fromAccountId),
                    fromUser.getLoggableName()
                        + " (account id "
                        + trialConfig.scannerConfig.fromAccountId
                        + ") has no full name or preferred email")));
      }
      if (!account.isActive()) {
        trialConfig.scannerConfig.messages.add(
            ScannerConfig.warningMessage(
                trialConfig.scannerConfig.pluginKeyValueMessage(
                    ScannerConfig.KEY_FROM,
                    Long.toString(trialConfig.scannerConfig.fromAccountId),
                    fromUser.getLoggableName()
                        + " (account id "
                        + trialConfig.scannerConfig.fromAccountId
                        + ") account is no longer active")));
      }
    } else if (fromUser != null && !fromUser.getUserName().isPresent()) {
      trialConfig.scannerConfig.messages.add(
          ScannerConfig.warningMessage(
              trialConfig.scannerConfig.pluginKeyValueMessage(
                  ScannerConfig.KEY_FROM,
                  Long.toString(trialConfig.scannerConfig.fromAccountId),
                  fromUser.getLoggableName()
                      + " (account id "
                      + trialConfig.scannerConfig.fromAccountId
                      + ") has no user name")));
    }
  }

  /**
   * Confirms whether submitter ran {@code main} and copied the output to the commit message.
   *
   * <p>When a new commit alters the configured scanner patterns, the push will fail with a message
   * to download the plugin source, to run a shell script that runs {@code main} below, and to copy
   * the output on success into the commit message.
   *
   * <p>This method scans the commit message to find the copied text. If the text was created for
   * the same pattern signagure, this method returns a single valid finding with the number of
   * microseconds it took to scan a large file, which can be used to block patterns that cause
   * excessive backtracking.
   *
   * <p>If the commit message contains one or more copied texts for other pattern signatures, this
   * method retuns an invalid finding for each.
   *
   * <p>If the commit message contains no copied texts, this method returns an empty list of
   * findings, which {@link com.googlesource.gerrit.plugins.copyright.CopyrightConfig} uses as a
   * signal to instruct the submitter to run the shell script in the first place.
   *
   * @param commitMessage from the pushed change
   */
  public ImmutableList<CopyrightReviewApi.CommitMessageFinding> checkCommitMessage(
      String commitMessage) {
    Preconditions.checkArgument(hasScanner(this));

    Pattern pattern =
        Pattern.compile(
            "Copyright-check:\\s*([\\p{N}a-fA-F]{1,9})[.]([\\p{N}a-fA-F]{16})\\s*(?:\n|$)",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.UNICODE_CASE | Pattern.DOTALL);
    Matcher m = pattern.matcher(commitMessage);
    ImmutableList.Builder<CopyrightReviewApi.CommitMessageFinding> builder =
        ImmutableList.builder();
    StringBuilder sb = new StringBuilder();
    while (m.find()) {
      sb.setLength(0);
      sb.append(m.group(1));
      sb.append("us");
      sb.append(scannerConfig.patternSignature);
      String signature =
          Hashing.farmHashFingerprint64().hashBytes(sb.toString().getBytes(UTF_8)).toString();
      if (signature.equals(m.group(2))) {
        return ImmutableList.of(
            new CopyrightReviewApi.CommitMessageFinding(
                commitMessage, m.group(), m.group(1), m.start(), m.end()));
      }
      logger.atSevere().log("signature for %s is %s", m.group(1), signature);
      builder.add(
          new CopyrightReviewApi.CommitMessageFinding(
              commitMessage, m.group(), m.start(), m.end()));
    }
    return builder.build();
  }

  /**
   * Returns true when {@code findings} indicate a problem to correct.
   *
   * <p>Problems include finding no time signature, finding a time signature for a different commit,
   * or finding a valid time signature for a test that took longer than {@code maxElapsedSeconds}.
   */
  public static boolean mustReportFindings(
      ImmutableList<CopyrightReviewApi.CommitMessageFinding> findings, long maxElapsedSeconds) {
    if (findings.size() == 1 && findings.get(0).isValid()) {
      return findings.get(0).elapsedMicros > maxElapsedSeconds * 1000000;
    }
    return true;
  }

  /** Returns true when {@code trialConfig} is non-null and has a non-null {@code scanner}. */
  public static boolean hasScanner(CheckConfig trialConfig) {
    if (trialConfig == null || trialConfig.scannerConfig == null) {
      return false;
    }
    return trialConfig.scannerConfig.scanner != null;
  }

  /** Returns true when both configs, {@code a} and {@code b}, have the same scanner pattern. */
  public static boolean scannersEqual(CheckConfig a, CheckConfig b) {
    if (!hasScanner(a)) {
      return !hasScanner(b);
    }
    return Objects.equals(a.scannerConfig.scanner, b.scannerConfig.scanner);
  }

  /** Checks whether {@code trialConfig} might cause excessive backtracking. */
  private long timeLargeFileInMicros() throws IOException {
    long startNanos = System.nanoTime();
    try {
      IndexedLineReader file = largeFile();
      scannerConfig.scanner.findMatches("file", -1, file);
    } finally {
      long elapsedNanos = System.nanoTime() - startNanos;
      long elapsedMicros = elapsedNanos / 1000;
      logger.atFine().log("timeLargeFile %dms", elapsedMicros / 1000);
      return elapsedMicros;
    }
  }

  /** Returns {@code IndexedLineReader} for in-memory pattern that can trigger backtracking. */
  private IndexedLineReader largeFile() {
    StringBuilder sb = new StringBuilder();
    sb.append("                                                                "); // 64 spaces
    sb.append(sb); // 128
    sb.append(sb); // 256
    sb.append(sb); // 512
    sb.append(sb); // 1024
    sb.append('\n');
    String space1k = sb.toString();

    sb.setLength(0);
    for (int i = 0; i < 256; i++) {
      sb.append(String.format(" x%2x", i));
    }
    sb.append('\n');
    String mixed1k = sb.toString();

    sb.setLength(0);
    for (int i = 255; i >= 0; i--) {
      sb.append(String.format(", %2x", i));
    }
    sb.append('\n');
    String comma1k = sb.toString();

    sb.setLength(0);
    for (int i = 255; i >= 0; i--) {
      sb.append(String.format("%2x%2x", 255-i, i));
    }
    sb.append('\n');
    String alnum1k = sb.toString();

    sb.setLength(0);
    sb.append("AbcdefGhijkLmnopQrstuVwxyzaBCDEFgHIJKlMNOPqRSTUvWXYZaeiouyAEIUOY"); // 64
    sb.append(sb); // 128
    sb.append(sb); // 256
    sb.append(sb); // 512
    sb.append(sb); // 1024
    sb.append('\n');
    String alpha1k = sb.toString();

    for (int i = 0; i < 16; i++) {  // 16k + 48k = 64k
      sb.append(space1k);
    }
    for (int i = 0; i < 48; i++) {
      sb.append(space1k, 0, 512 - 10 * i);
      sb.append(mixed1k, 512 + 10 * i, mixed1k.length());
    }

    for (int i = 0; i < 16; i++) { // 64k + 16k + 48k = 128k
      sb.append(alnum1k);
    }
    for (int i = 0; i < 48; i++) {
      sb.append(comma1k);
    }

    for (int i = 0; i < 16; i++) { // 128k + 16k + 48k = 192k
      sb.append(mixed1k);
    }
    for (int i = 0; i < 48; i++) {
      sb.append(alpha1k);
    }

    for (int i = 0; i < 16; i++) { // 192k + 16k + 48k = 256k
      sb.append(alpha1k);
    }
    for (int i = 0; i < 48; i++) {
      sb.append(space1k, 0, 512 - 10 * i);
      sb.append(comma1k, 512 + 10 * i, comma1k.length());
    }

    return new IndexedLineReader(
        "big_file", -1, new ByteArrayInputStream(sb.toString().getBytes(UTF_8)));
  }

  /** Output validation messages on the error console. */
  private void printErrors() {
    for (CommitValidationMessage message : scannerConfig.messages) {
      System.err.printf("%s: %s\n", message.getType(), message.getMessage());
    }
  }

  /** Output a usage message on the error console. */
  private static void usage() {
    System.err.printf(
        "%s <plugin-name> <project.config>\n  where:\n"
            + "    <plugin-name> is the name of the plugin. e.g. 'copyright'\n"
            + "    <project.config> is the path to the project.config file\n",
        toolName);
    System.exit(1);
  }

  /** Read the contents of a project.config file from {@code ilr}. */
  private static String readProjectConfigFile(IndexedLineReader ilr) throws IOException {
    StringBuilder sb = new StringBuilder();
    CharBuffer cb = CharBuffer.wrap(BUFFER);
    while (ilr.read(cb) >= 0) {
      cb.flip();
      sb.append(cb);
      cb.clear();
    }
    String contents = sb.toString();
    sb.setLength(0);
    sb = null;
    return contents;
  }

  /** Calculates the time signature for {@code elapsedMicros} and the current scanner pattern. */
  @VisibleForTesting
  String timeSignature(long elapsedMicros) {
    StringBuilder sb = new StringBuilder();
    sb.append(Long.toString(elapsedMicros));
    sb.append("us");
    sb.append(scannerConfig.patternSignature);

    return Hashing.farmHashFingerprint64().hashBytes(sb.toString().getBytes(UTF_8)).toString();
  }

  /** Entry point for command-line tool to check for excessive backtracking. */
  public static void main(String[] args) {
    if (args.length != 2) {
      usage();
    }
    String pluginName = args[0];
    String fileName = args[1].trim();
    try {
      IndexedLineReader ilr =
          new IndexedLineReader(
              fileName, Paths.get(fileName).toFile().length(), new FileInputStream(fileName));
      CheckConfig myConfig = new CheckConfig(pluginName, readProjectConfigFile(ilr));
      checkProjectConfig(null, false, myConfig);
      if (myConfig.scannerConfig.hasErrors()) {
        myConfig.printErrors();
        System.exit(1);
      }
      Preconditions.checkNotNull(myConfig.scannerConfig.scanner);

      long elapsedMicros = myConfig.timeLargeFileInMicros();
      Preconditions.checkArgument(elapsedMicros >= 0);

      if (elapsedMicros > 1000000) { // longer than a second migth be a problem...
        System.err.println(
            "\n\nThis tool used your copyright plugin config against a large, hard-");
        System.err.println("to-scan file.");
        System.err.println(
            "\nEven for large, difficult to scan files, it's best to keep scan times");
        System.err.println("below 1 second, due to load on the server.\n");
        System.err.println(CopyrightReviewApi.typicalBacktrackingCauses());
        if (elapsedMicros > 60000000) { // minutes is way too long on any server...
          System.err.printf(
              "\nAt %ds, the scan took longer than %d minutes! Please change\n",
              elapsedMicros / 1000000, elapsedMicros / 60000000);
          System.err.println("whatever pattern causes the problem befure submitting.");
        } else if (elapsedMicros > 10000000) { // tens of seconds is too long on any server...
          System.err.printf(
              "\nThe scan took longer than %d seconds! It's very likely this\n",
              elapsedMicros / 1000000);
          System.err.println(
              "configuration will cause problems on your server. Please try to change");
          System.err.println("whatever pattern causes the problem.");
        } else if (elapsedMicros > 2000000) { // multiple seconds is likely a problem...
          System.err.printf(
              "\nThe scan took longer than %d seconds. It's possible this configuration\n",
              elapsedMicros / 1000000);
          System.err.println(
              "might cause problems on your server. Please compare wtih the current");
          System.err.println(
              "configuration, and if this configuration is significantly slower,");
          System.err.println("consider changing whatever pattern might cause the problem.");
        } else { // between 1s and 2s might be needed but could at least try to do better
          System.err.printf(
              "\nAt %dms, the scan took just longer than 1 second. This\n", elapsedMicros / 1000);
          System.err.println(
              "configuration might work okay, but takes longer than ideal. Please");
          System.err.println(
              "investigate whether an added pattern is more costly than needed.");
        }
      } else if (elapsedMicros > 1000) {
        System.err.printf("\nScanned the test load in %dms.\n", elapsedMicros / 1000);
      } else {
        System.err.printf("\nScanned the test load in %d microseconds.\n", elapsedMicros);
      }

      String signature = myConfig.timeSignature(elapsedMicros);
      System.out.println("\n\nCopy the line below into your commit message:");
      System.out.printf("\nCopyright-check: %x.%s\n\n\n", elapsedMicros, signature);
      System.exit(0);
    } catch (IOException e) {
      System.err.printf("Could not read %s\n%s\n", fileName, e.getMessage());
      System.exit(1);
    } catch (ConfigInvalidException e) {
      System.err.printf("Could not parse %s\n%s\n", fileName, e.getMessage());
      System.exit(1);
    }
  }
}
