// 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 com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.MatchType.AUTHOR_OWNER;
import static com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.MatchType.LICENSE;
import static com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.PartyType.FIRST_PARTY;
import static com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.PartyType.FORBIDDEN;
import static com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.PartyType.THIRD_PARTY;
import static com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.PartyType.UNKNOWN;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput;
import com.google.gerrit.extensions.api.changes.ReviewResult;
import com.google.gerrit.extensions.client.Comment;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.events.RevisionCreatedListener;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.metrics.Counter0;
import com.google.gerrit.metrics.Counter1;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.Field;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.PluginUser;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.git.validators.CommitValidationException;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.restapi.change.ListChangeComments;
import com.google.gerrit.server.restapi.change.PostReview;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.Match;
import com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.MatchType;
import com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.PartyType;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;

/** Utility to report revision findings on the review thread. */
@Singleton
public class CopyrightReviewApi {
  static final ImmutableList<Match> ALWAYS_REVIEW = ImmutableList.of();

  private final Metrics metrics;
  private final Provider<PluginUser> pluginUserProvider;
  private final Provider<CurrentUser> userProvider;
  private final IdentifiedUser.GenericFactory identifiedUserFactory;
  private final ChangeNotes.Factory changeNotesFactory;
  private final ChangeResource.Factory changeResourceFactory;
  private final PatchSetUtil psUtil;
  private final PostReview postReview;
  private final ListChangeComments listChangeComments;

  @Singleton
  static class Metrics {
    final Counter0 reviewCount;
    final Counter0 commentCount;
    final Timer0 reviewTimer;
    final Counter1 reviewCountByProject;
    final Counter1 commentCountByProject;
    final Timer1 reviewTimerByProject;

    @Inject
    Metrics(MetricMaker metricMaker) {
      Field<String> project = Field.ofString("project", "project name");
      reviewCount =
          metricMaker.newCounter(
              "plugin/copyright/review_count",
              new Description("Total number of posted reviews").setRate().setUnit("reviews"));
      commentCount =
          metricMaker.newCounter(
              "plugin/copyright/comment_count",
              new Description("Total number of posted review comments")
                  .setRate()
                  .setUnit("comments"));
      reviewTimer =
          metricMaker.newTimer(
              "plugin/copyright/review_latency",
              new Description("Time spent posting reviews to revisions")
                  .setCumulative()
                  .setUnit(Units.MICROSECONDS));
      reviewCountByProject =
          metricMaker.newCounter(
              "plugin/copyright/review_count_by_project",
              new Description("Total number of posted reviews").setRate().setUnit("reviews"),
              project);
      commentCountByProject =
          metricMaker.newCounter(
              "plugin/copyright/comment_count_by_project",
              new Description("Total number of posted review comments")
                  .setRate()
                  .setUnit("comments"),
              project);
      reviewTimerByProject =
          metricMaker.newTimer(
              "plugin/copyright/review_latency_by_project",
              new Description("Time spent posting reviews to revisions")
                  .setCumulative()
                  .setUnit(Units.MICROSECONDS),
              project);
    }
  }

  @Inject
  CopyrightReviewApi(
      Metrics metrics,
      Provider<PluginUser> pluginUserProvider,
      Provider<CurrentUser> userProvider,
      IdentifiedUser.GenericFactory identifiedUserFactory,
      ChangeNotes.Factory changeNotesFactory,
      ChangeResource.Factory changeResourceFactory,
      PatchSetUtil psUtil,
      PostReview postReview,
      ListChangeComments listChangeComments) {
    this.metrics = metrics;
    this.pluginUserProvider = pluginUserProvider;
    this.userProvider = userProvider;
    this.identifiedUserFactory = identifiedUserFactory;
    this.changeNotesFactory = changeNotesFactory;
    this.changeResourceFactory = changeResourceFactory;
    this.psUtil = psUtil;
    this.postReview = postReview;
    this.listChangeComments = listChangeComments;
  }

  /**
   * Reports failure findings from or about the check_new_config.sh tool on the review thread.
   *
   * <p>If no output found in the commit message, directs the submitter to run the tool and copy its
   * output into the commit message.
   *
   * <p>If the output was found for a different scanner pattern, directs the submitter to run again
   * for the current commit.
   *
   * <p>Otherwise, the duration of the timing run must exceed the configured limit. Describes
   * patterns known to cause problems and directs the submitter to change the pattern.
   *
   * @param pluginName as installed in gerrit
   * @param project identifies the All-Projects config for recording metrics
   * @param oldConfig the prior state of the plugin configuration
   * @param newConfig the new state of the plugin configuration
   * @param event describes the pushed revision with the new configuration
   * @param findings describes the line numbers, validity and timing run durations found
   * @param maxElapsedSeconds the largest allows timing run duration in seconds
   * @throws RestApiException if an error occurs updating the review thread
   */
  ReviewResult reportCommitMessageFindings(
      String pluginName,
      String project,
      ScannerConfig oldConfig,
      ScannerConfig newConfig,
      RevisionCreatedListener.Event event,
      ImmutableList<CommitMessageFinding> findings,
      long maxElapsedSeconds)
      throws RestApiException {
    Preconditions.checkNotNull(newConfig);
    Preconditions.checkNotNull(newConfig.scanner);
    Preconditions.checkArgument(
        oldConfig == null
            || oldConfig.scanner == null
            || !oldConfig.scanner.equals(newConfig.scanner));
    Preconditions.checkArgument(findings.size() != 1 || !findings.get(0).isValid());
    Preconditions.checkArgument(maxElapsedSeconds > 0);

    long startNanos = System.nanoTime();
    metrics.reviewCount.increment();
    metrics.reviewCountByProject.increment(project);

    int fromAccountId =
        oldConfig != null && oldConfig.fromAccountId > 0
            ? oldConfig.fromAccountId
            : newConfig.fromAccountId;
    ChangeResource change = getChange(event, fromAccountId);
    Map<String, List<CommentInfo>> priorReviewComments = getComments(change);
    if (priorReviewComments == null) {
      priorReviewComments = ImmutableMap.of();
    }
    HashSet<CommentInfo> priorComments = new HashSet<>();
    priorComments.addAll(priorReviewComments.get("/COMMIT_MSG"));

    ReviewInput ri = new ReviewInput();
    ri.message(getCommitMessageMessage(pluginName, findings, maxElapsedSeconds));
    ImmutableList<CommentInput> comments =
        ImmutableList.copyOf(
            getCommitMessageComments(pluginName, findings, maxElapsedSeconds).stream()
                .filter(ci -> !priorComments.contains(ci))
                .toArray(i -> new CommentInput[i]));
    if (!comments.isEmpty()) {
      ri.comments = ImmutableMap.of("/COMMIT_MSG", comments);
    }
    String label = "Code-Review";
    if (!Strings.isNullOrEmpty(oldConfig.reviewLabel)) {
      label = oldConfig.reviewLabel;
    } else if (!Strings.isNullOrEmpty(newConfig.reviewLabel)) {
      label = newConfig.reviewLabel;
    }
    int vote = (findings.size() != 1 || !findings.get(0).isValid()) ? -2 : 2;
    if (vote == 2) {
      long elapsedMicros = findings.get(0).elapsedMicros;
      if (elapsedMicros > maxElapsedSeconds * 1000000) {
        vote = -2;
      } else if (elapsedMicros > 2000000) {
        vote = 1;
      }
    }
    ri.label(label, vote);
    return review(change, ri);
  }

  /**
   * Returns a {@link com.google.gerrit.server.git.validators.CommitValidationException} describing
   * failure findings from or about the check_new_config.sh tool.
   *
   * <p>If no output found in the commit message, directs the submitter to run the tool and copy its
   * output into the commit message.
   *
   * <p>If the output was found for a different scanner pattern, directs the submitter to run again
   * for the current commit.
   *
   * <p>Otherwise, the duration of the timing run must exceed the configured limit. Describes
   * patterns known to cause problems and directs the submitter to change the pattern.
   *
   * @param pluginName as installed in gerrit
   * @param findings describes the line numbers, validity and timing run durations found
   * @param maxElapsedSeconds the largest allows timing run duration in seconds
   */
  public CommitValidationException getCommitMessageException(
      String pluginName, ImmutableList<CommitMessageFinding> findings, long maxElapsedSeconds) {
    Preconditions.checkArgument(
        findings.size() != 1
            || !findings.get(0).isValid()
            || findings.get(0).elapsedMicros > maxElapsedSeconds * 1000000);
    StringBuilder sb = new StringBuilder();
    sb.append(getCommitMessageMessage(pluginName, findings, maxElapsedSeconds));
    sb.append("\n\n");
    ImmutableList<CommentInput> comments =
        getCommitMessageComments(pluginName, findings, maxElapsedSeconds);
    for (CommentInput ci : comments) {
      if (ci.line != 0) {
        sb.append("commit message line ");
        sb.append(Integer.toString(ci.range.startLine));
        sb.append(":\n");
      }
      sb.append(ci.message);
      sb.append("\n");
    }
    return new CommitValidationException(sb.toString());
  }

  /**
   * Reports validation findings for a proposed new plugin configuration to the review thread for
   * the newly pushed revision.
   *
   * @param pluginName as installed in gerrit
   * @param project identifies the All-Projects config for recording metrics
   * @param path identifies the file to attach messages to (@code gerrit.config or project.config}
   * @param oldConfig the prior state of the plugin configuration
   * @param newConfig the new state of the plugin configuration
   * @param event describes the pushed revision with the new configuration
   * @throws RestApiException if an error occurs updating the review thread
   */
  ReviewResult reportConfigMessages(
      String pluginName,
      String project,
      String path,
      ScannerConfig oldConfig,
      ScannerConfig newConfig,
      RevisionCreatedListener.Event event)
      throws RestApiException {
    Preconditions.checkNotNull(newConfig);
    Preconditions.checkNotNull(newConfig.messages);
    Preconditions.checkArgument(!newConfig.messages.isEmpty());

    long startNanos = System.nanoTime();
    metrics.reviewCount.increment();
    metrics.reviewCountByProject.increment(project);

    try {
      int fromAccountId =
          oldConfig != null && oldConfig.fromAccountId > 0
              ? oldConfig.fromAccountId
              : newConfig.fromAccountId;
      ChangeResource change = getChange(event, fromAccountId);
      StringBuilder message = new StringBuilder();
      message.append(pluginName);
      message.append(" plugin issues parsing new configuration");
      ReviewInput ri = new ReviewInput().message(message.toString());

      Map<String, List<CommentInfo>> priorComments = getComments(change);
      if (priorComments == null) {
        priorComments = ImmutableMap.of();
      }

      int numComments = 0;
      ImmutableMap.Builder<String, List<CommentInput>> comments = ImmutableMap.builder();
      for (CommitValidationMessage m : newConfig.messages) {
        message.setLength(0);
        message.append(m.getType().toString());
        message.append(" ");
        message.append(m.getMessage());
        CommentInput ci = new CommentInput();
        ci.line = 0;
        ci.unresolved = true;
        ci.message = message.toString();
        if (containsComment(priorComments.get(path), ci)) {
          continue;
        }
        comments.put(path, ImmutableList.of(ci));
        numComments++;
      }
      if (numComments > 0) {
        ri.comments = comments.build();
      }
      metrics.commentCount.incrementBy((long) numComments);
      metrics.commentCountByProject.incrementBy(project, (long) numComments);
      return review(change, ri);
    } finally {
      long elapsedMicros = (System.nanoTime() - startNanos) / 1000;
      metrics.reviewTimer.record(elapsedMicros, TimeUnit.MICROSECONDS);
      metrics.reviewTimerByProject.record(project, elapsedMicros, TimeUnit.MICROSECONDS);
    }
  }

  /**
   * Reports {@link CopyrightValidator} findings from a scanned revision on its review thread.
   *
   * @param project identifies the project where change pushed for recording metrics
   * @param scannerConfig the state of the plugin configuration and scanner
   * @param event describes the pushed revision scanned by the plugin
   * @param findings maps each scanned file to the copyright matches found by the scanner
   * @throws RestApiException if an error occurs updating the review thread
   */
  ReviewResult reportScanFindings(
      String project,
      ScannerConfig scannerConfig,
      RevisionCreatedListener.Event event,
      Map<String, ImmutableList<Match>> findings)
      throws RestApiException {
    long startNanos = System.nanoTime();
    metrics.reviewCount.increment();
    metrics.reviewCountByProject.increment(project);

    try {
      boolean tpAllowed = scannerConfig.isThirdPartyAllowed(project);
      boolean reviewRequired = false;
      for (Map.Entry<String, ImmutableList<Match>> entry : findings.entrySet()) {
        if (entry.getValue() == ALWAYS_REVIEW) {
          reviewRequired = true;
          break;
        }
        PartyType pt = partyType(entry.getValue());
        if (pt.compareTo(THIRD_PARTY) > 0) {
          reviewRequired = true;
          break;
        }
        if (pt == THIRD_PARTY && !tpAllowed) {
          reviewRequired = true;
          break;
        }
      }
      ChangeResource change = getChange(event, scannerConfig.fromAccountId);
      ReviewInput ri =
          new ReviewInput()
              .message("Copyright scan")
              .label(scannerConfig.reviewLabel, reviewRequired ? -1 : +2);

      if (reviewRequired) {
        ri = addReviewers(ri, scannerConfig.ccs, ReviewerState.CC);
        ri = addReviewers(ri, scannerConfig.reviewers, ReviewerState.REVIEWER);
      }
      ImmutableMap.Builder<String, List<CommentInput>> comments = ImmutableMap.builder();
      if (reviewRequired) {
        ri = ri.message("This change requires copyright review.");
      } else {
        ri = ri.message("This change appears to comply with copyright requirements.");
      }
      Map<String, List<CommentInfo>> priorComments = getComments(change);
      if (priorComments == null) {
        priorComments = ImmutableMap.of();
      }

      int numCommentsAdded = 0;
      for (Map.Entry<String, ImmutableList<Match>> entry : findings.entrySet()) {
        ImmutableList<CommentInput> newComments = null;
        if (entry.getValue() == ALWAYS_REVIEW) {
          CommentInput ci = new CommentInput();
          ci.line = 0;
          ci.unresolved = true;
          ci.message = entry.getKey() + " always requires copyright review";
          if (containsComment(priorComments.get(entry.getKey()), ci)) {
            continue;
          }
          newComments = ImmutableList.of(ci);
        } else {
          PartyType pt = partyType(entry.getValue());
          newComments = reviewComments(project, pt, tpAllowed, entry.getValue());
          List<CommentInfo> prior = priorComments.get(entry.getKey());
          newComments =
              ImmutableList.copyOf(
                  newComments.stream()
                      .filter(ci -> !containsComment(prior, ci))
                      .toArray(i -> new CommentInput[i]));
          if (newComments.isEmpty()) {
            continue;
          }
        }
        numCommentsAdded += newComments.size();
        comments.put(entry.getKey(), newComments);
      }

      if (numCommentsAdded > 0) {
        ri.comments = comments.build();
      }
      metrics.commentCount.incrementBy((long) numCommentsAdded);
      metrics.commentCountByProject.incrementBy(project, (long) numCommentsAdded);
      return review(change, ri);
    } finally {
      long elapsedMicros = (System.nanoTime() - startNanos) / 1000;
      metrics.reviewTimer.record(elapsedMicros, TimeUnit.MICROSECONDS);
      metrics.reviewTimerByProject.record(project, elapsedMicros, TimeUnit.MICROSECONDS);
    }
  }

  /**
   * Returns the {@link com.google.gerrit.server.CurrentUser} seeming to send the review comments.
   *
   * <p>Impersonates {@code fromAccountId} if configured by {@code fromAccountId =} in plugin
   * configuration -- falling back to the identity of the user pushing the revision.
   */
  CurrentUser getSendingUser(int fromAccountId) {
    PluginUser pluginUser = pluginUserProvider.get();
    return fromAccountId <= 0
        ? userProvider.get()
        : identifiedUserFactory.runAs(null, new Account.Id(fromAccountId), pluginUser);
  }

  /**
   * Returns 1 of 3 review messages depending on the check_new_config.sh tool output.
   *
   * @param pluginName as installed in gerrit
   * @param findings describes the line numbers, validity and timing run durations found
   */
  private String getCommitMessageMessage(
      String pluginName, ImmutableList<CommitMessageFinding> findings, long maxElapsedSeconds) {
    StringBuilder sb = new StringBuilder();
    if (findings.isEmpty()) {
      sb.append(pluginName);
      sb.append(" plugin: match patterns have changed; please run check_new_config tool");
    } else if (findings.size() == 1 && findings.get(0).isValid()) {
      long elapsedMicros = findings.get(0).elapsedMicros;
      if (elapsedMicros > maxElapsedSeconds * 1000000) {
        sb.append("check_new_config: problem pattern detected");
      } else if (elapsedMicros > 2000000) {
        sb.append("check_new_config: possible problem pattern detected");
      } else if (elapsedMicros > 1000000) {
        sb.append("check_new_config: possibly okay");
      } else {
        sb.append("check_new_config: okay");
      }
    } else {
      sb.append("check_new_config: results for wrong commit; please run again for current");
    }
    return sb.toString();
  }

  /**
   * Returns one or more of 3 review comment versions based on the check_new_config.sh tool output.
   *
   * @param pluginName as installed in gerrit
   * @param findings describes the line numbers, validity and timing run durations found
   * @param maxElapsedSeconds the largest allows timing run duration in seconds
   */
  private ImmutableList<CommentInput> getCommitMessageComments(
      String pluginName, ImmutableList<CommitMessageFinding> findings, long maxElapsedSeconds) {
    ImmutableList.Builder<CommentInput> comments = ImmutableList.builder();
    StringBuilder sb = new StringBuilder();
    CommentInput ci = new CommentInput();
    if (findings.isEmpty()) {
      sb.append("While most patterns are fine, some patterns can force your gerrit server\n");
      sb.append("to work too hard. To protect your server, there is a tool that can\n");
      sb.append("detect these patterns before the configuration gets submitted.\n\n");
      sb.append("Please use git to download the tool from:\n");
      sb.append("https://gerrit.googlesource.com/plugins/copyright/+/refs/heads/master\n\n");
      sb.append("After downloading, run tools/check_new_config.sh (requires bazel):\n");
      sb.append("<path>/tools/check_new_config.sh '");
      sb.append(pluginName);
      sb.append("' '<path>/project.config'\n");
      sb.append("and copy it's output to your commit message.\n\n");
      sb.append("e.g. if your local All-Projects is at workspace/All-Projects and if you\n");
      sb.append("downloaded plugins/copyright to workspace/copyright, you might run:\n");
      sb.append("../copyright/tools/check_new_config.sh '");
      sb.append(pluginName);
      sb.append("' project.config\n");
      sb.append("from the workspace/All-Projects directory.\n");
      ci.line = 0;
      ci.unresolved = true;
      ci.message = sb.toString();
      comments.add(ci);
    } else if (findings.size() == 1 && findings.get(0).isValid()) {
      CommitMessageFinding finding = findings.get(0);
      if (finding.elapsedMicros > maxElapsedSeconds * 1000000) {
        sb.append("Scanning the test file took longer than ");
        sb.append(Long.toString(maxElapsedSeconds));
        sb.append(" seconds.");
        if (finding.elapsedMicros - (maxElapsedSeconds * 1000000) > 1000000) {
          sb.append(" (");
          sb.append(Long.toString(finding.elapsedMicros / 1000000));
          sb.append(" seconds)");
        }
        sb.append("\n\nThis is much longer than usual even on a slower, modern computer.\n\n");
        sb.append("The result suggests a pattern that causes excessive backtracking.\n");
        sb.append(typicalBacktrackingCauses());
        sb.append("\nPlease fix any problematic patterns and try again.\n");
      } else if (finding.elapsedMicros > 2000000) {
        sb.append("Scanning the test file took longer than 2 seconda. (");
        if (finding.elapsedMicros > 3000000) {
          sb.append(Long.toString(finding.elapsedMicros / 1000000));
          sb.append(" seconds)");
        } else {
          sb.append(Long.toString(finding.elapsedMicros / 1000));
          sb.append(" ms)");
        }
        sb.append("\n\nThe result suggests a pattern that might cause excessive backtracking.\n");
        sb.append(typicalBacktrackingCauses());
        sb.append("\nPlease try to fix any problematic patterns before proceeding.\n");
      } else if (finding.elapsedMicros > 1000000) {
        sb.append("Scanning the test file took just longer than a second. (");
        sb.append(Long.toString(finding.elapsedMicros / 1000));
        sb.append("ms)");
        sb.append("\n\nThe result is a little longer than ideal.\n\n");
        sb.append(typicalBacktrackingCauses());
        sb.append("\n\nCompare with the current config, and if this config is signigicantly\n");
        sb.append("slower, consider changing whatever pattern causes the problem.\n");
      } else if (finding.elapsedMicros > 1000) {
        sb.append("Scanning the test file took ");
        sb.append(Long.toString(finding.elapsedMicros / 1000));
        sb.append("ms.");
      } else {
        sb.append("Scanning the test file took ");
        sb.append(Long.toString(finding.elapsedMicros));
        sb.append(" microsends.");
      }
      ci.line = finding.endLine;
      ci.range = new CommentInput.Range();
      ci.range.startLine = finding.startLine;
      ci.range.endLine = finding.endLine;
      ci.range.startCharacter = finding.startCol;
      ci.range.endCharacter = finding.endCol;
      ci.unresolved = finding.elapsedMicros > 1000000;
      ci.message = sb.toString();
      comments.add(ci);
    } else {
      for (CommitMessageFinding finding : findings) {
        sb.setLength(0);
        sb.append("'");
        sb.append(finding.text.trim());
        sb.append("'\nis not a result for the patterns in the current revision");
        ci.line = finding.endLine;
        ci.range = new CommentInput.Range();
        ci.range.startLine = finding.startLine;
        ci.range.endLine = finding.endLine;
        ci.range.startCharacter = finding.startCol;
        ci.range.endCharacter = finding.endCol;
        ci.unresolved = true;
        ci.message = sb.toString();
        comments.add(ci);
        ci = new CommentInput();
      }
    }
    return comments.build();
  }

  public static String typicalBacktrackingCauses() {
    StringBuilder sb = new StringBuilder();
    sb.append("Typical causes of excessive backtracking include:\n");
    sb.append("  1. unbounded repetitions of wildcards or\n");
    sb.append("  2. zero-length look-ahead/look-behind patterns\n\n");
    sb.append("Wildcards:\n");
    sb.append("  The scanner automatically handles .* and .+ patterns, but it's\n");
    sb.append("  possible to accidentally compose equivalents or near-equivalents:\n");
    sb.append("  e.g. (?:[a]|[^a])* or [\\\\s\\\\p{N}\\\\p{L}\\\\p{P}]+ match nearly everything\n");
    sb.append("  If your new pattern contains something similar, consider using .* for\n");
    sb.append("  automatic handling instead, or use a smaller character class.\n\n");
    sb.append("Unbounded repetitions:\n");
    sb.append("  If your new pattern uses * or + for unlimited repetitions, consider\n");
    sb.append("  using a more limited repetition like {0,10} or {1,50} that is long\n");
    sb.append("  enough to match what you need but short enough to scan quickly.\n\n");
    sb.append("Zero-length look-ahead or look-behind:\n");
    sb.append("  Patterns like (?!word), (?=word), (?<!word). (?<=word) etc. can cause\n");
    sb.append("  excessive backtracking too. Sometimes, it is faster to match a little\n");
    sb.append("  more than needed and use an excludePattern to eliminate unwanted hits.\n");
    sb.append("  e.g. forbiddenPattern = owner some pattern \\p{L}*\n");
    sb.append("       excludePattern = some pattern word\n");
    return sb.toString();
  }

  /**
   * Constructs a {@link com.google.gerrit.server.change.ChangeResource} from the notes log for the
   * change onto which a new revision was pushed.
   *
   * @param event describes the newly pushed revision
   * @param fromAccountId identifies the configured user to impersonate when sending review comments
   * @throws RestApiException if an error occurs looking up the notes log for the change
   */
  private ChangeResource getChange(RevisionCreatedListener.Event event, int fromAccountId)
      throws RestApiException {
    try {
      CurrentUser fromUser = getSendingUser(fromAccountId);
      ChangeNotes notes =
          changeNotesFactory.createChecked(new Change.Id(event.getChange()._number));
      return changeResourceFactory.create(notes, fromUser);
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      throw e instanceof RestApiException
          ? (RestApiException) e
          : new RestApiException("Cannot load change", e);
    }
  }

  /**
   * Returns a modified {@link com.google.gerrit.extensions.api.changes.ReviewInput} after adding
   * {@code reviewers} as {@code type} CC or REVIEWER.
   */
  @VisibleForTesting
  ReviewInput addReviewers(ReviewInput ri, Iterable<String> reviewers, ReviewerState type) {
    for (String reviewer : reviewers) {
      ri = ri.reviewer(reviewer, type, true);
    }
    return ri;
  }

  /**
   * Retrieves all of the prior review comments already attached to {@code change}.
   *
   * @throws RestApiException if an error occurs retrieving the comments
   */
  private Map<String, List<CommentInfo>> getComments(ChangeResource change)
      throws RestApiException {
    try {
      return listChangeComments.apply(change);
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      throw e instanceof RestApiException
          ? (RestApiException) e
          : new RestApiException("Cannot list comments", e);
    }
  }

  /**
   * Adds the code review described by {@code ri} to the review thread of {@code change}.
   *
   * @throws RestApiException if an error occurs updating the review thread
   */
  private ReviewResult review(ChangeResource change, ReviewInput ri) throws RestApiException {
    try {
      PatchSet ps = psUtil.current(change.getNotes());
      if (ps == null) {
        throw new ResourceNotFoundException(IdString.fromDecoded("current"));
      }
      RevisionResource revision = RevisionResource.createNonCacheable(change, ps);
      return postReview.apply(revision, ri).value();
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      throw e instanceof RestApiException
          ? (RestApiException) e
          : new RestApiException("Cannot post review", e);
    }
  }

  /** Returns true if {@code priorComments} already includes a comment identical to {@code ci}. */
  @VisibleForTesting
  boolean containsComment(Iterable<? extends Comment> priorComments, CommentInput ci) {
    if (priorComments == null) {
      return false;
    }
    for (Comment prior : priorComments) {
      if (Objects.equals(prior.line, ci.line)
          && Objects.equals(prior.range, ci.range)
          && Objects.equals(prior.message, ci.message)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Puts the pieces together from a scanner finding to construct a coherent human-reable message.
   *
   * @param project describes the project or repository where the revision was pushed
   * @param overallPt identifies the calculated {@link
   *     com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.PartyType} for all of the
   *     findings in the file. e.g. 1p license + 3p owner == 1p, no license + 3p owner == 3p
   * @param pt identifies the {@code PartyType} of the current finding
   * @param mt identifies the {@link
   *     com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.MatchType} of the current
   *     finding. i.e. AUTHOR_OWNER or LICENSE
   * @param tpAllowed is true if {@code project} allows third-party code
   * @param text of the message for the finding
   */
  private String buildMessage(
      String project,
      PartyType overallPt,
      PartyType pt,
      MatchType mt,
      boolean tpAllowed,
      StringBuilder text) {
    StringBuilder message = new StringBuilder();
    switch (pt) {
      case FIRST_PARTY:
        message.append("First-party ");
        break;
      case THIRD_PARTY:
        message.append("Third-party ");
        break;
      case FORBIDDEN:
        message.append("Disapproved ");
        break;
      default:
        message.append("Unrecognized ");
        break;
    }
    message.append(mt == AUTHOR_OWNER ? "author or owner " : "license ");
    if (pt == THIRD_PARTY && overallPt != FIRST_PARTY) {
      if (!tpAllowed) {
        message.append("dis");
      }
      message.append("allowed in repository ");
      message.append(project);
    }
    message.append(":\n\n");
    message.append(text);
    return message.toString();
  }

  /**
   * Converts the scanner findings in {@code matches} into human-readable review comments.
   *
   * @param project the project or repository to which the revision was pushed
   * @param pt the calculated overall {@link
   *     com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.PartyType} for the findings
   *     e.g. 1p license + 3p owner = 1p, no license + 3p owner = 3p
   * @param tpAllowed is true if {@code project} allows third-party code
   * @param matches describes the location and types of matches found in a file
   * @return a list of {@link com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput} to
   *     add to the {@link com.google.gerrit.extensions.api.changes.ReviewInput} to add to the
   *     review thread for the current patch set.
   */
  @VisibleForTesting
  ImmutableList<CommentInput> reviewComments(
      String project, PartyType pt, boolean tpAllowed, Iterable<Match> matches) {
    ImmutableList.Builder<CommentInput> builder = ImmutableList.builder();
    CommentInput ci = null;
    PartyType previousPt = UNKNOWN;
    MatchType previousMt = LICENSE;
    StringBuilder text = new StringBuilder();
    for (Match m : matches) {
      if (ci == null
          || previousPt != m.partyType
          || m.endLine > ci.range.startLine + 60
          || m.startLine > ci.range.endLine + 40) {
        if (ci != null) {
          ci.message = buildMessage(project, pt, previousPt, previousMt, tpAllowed, text);
          builder.add(ci);
        }
        ci = new CommentInput();
        boolean allowed =
            m.partyType == FIRST_PARTY
                || (m.partyType == THIRD_PARTY && tpAllowed)
                || (m.partyType == THIRD_PARTY && m.matchType == AUTHOR_OWNER && pt == FIRST_PARTY);
        ci.unresolved = !allowed;
        ci.range = new Comment.Range();
        ci.line = m.endLine;
        ci.range.startLine = m.startLine;
        ci.range.endLine = m.endLine;
        ci.range.startCharacter = 0;
        ci.range.endCharacter = 0;
        previousPt = m.partyType;
        previousMt = m.matchType;
        text.setLength(0);
        text.append(m.text);
        continue;
      }
      text.append("...");
      text.append(m.text);
      // an author or owner inside a license declaration is a normal part of a license declaration
      if (m.matchType == LICENSE) {
        previousMt = LICENSE;
      }
      if (m.startLine < ci.range.startLine) {
        ci.range.startLine = m.startLine;
      }
      if (m.endLine > ci.range.endLine) {
        ci.range.endLine = m.endLine;
        ci.line = m.endLine;
      }
    }
    if (ci != null) {
      ci.message = buildMessage(project, pt, previousPt, previousMt, tpAllowed, text);
      builder.add(ci);
    }
    return builder.build();
  }

  /**
   * Calculates and returns the overall {@link
   * com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.PartyType} for the copyright
   * scanner findings in {@code matches}.
   */
  @VisibleForTesting
  PartyType partyType(Iterable<Match> matches) {
    PartyType pt = PartyType.FIRST_PARTY;
    boolean hasThirdPartyOwner = false;
    boolean hasFirstPartyLicense = false;
    for (Match match : matches) {
      if (match.partyType == PartyType.THIRD_PARTY && match.matchType == MatchType.AUTHOR_OWNER) {
        hasThirdPartyOwner = true;
      } else if (match.partyType == PartyType.FIRST_PARTY && match.matchType == MatchType.LICENSE) {
        hasFirstPartyLicense = true;
      } else if (match.partyType.compareTo(pt) > 0) {
        pt = match.partyType;
      }
    }
    if (pt == PartyType.FIRST_PARTY && hasThirdPartyOwner && !hasFirstPartyLicense) {
      return PartyType.THIRD_PARTY;
    }
    return pt;
  }

  /**
   * Found {@code main} output in the commit message.
   *
   * <p>Each finding identifies the position in the commit message, the validity for the current
   * scanner pattern, and the large file scan duration if valid.
   */
  public static class CommitMessageFinding {
    private static final Pattern NL = Pattern.compile("\n", Pattern.MULTILINE | Pattern.DOTALL);

    /** The character offset into the commit message where the finding starts. */
    public final int start;
    /** The character offset into the commit message where the finding ends. */
    public final int end;
    /** The found text apparently matching {@code main} output. */
    public final String text;
    /** How long in microseconds it took to scan a large file, or -1 if scan with other pattern. */
    public final long elapsedMicros;

    /** The line number of the start of the finding in the commit message. */
    public final int startLine;
    /** The column (0-based) of the start of the finding in the commit message. */
    public final int startCol;
    /** The line number of the end of the finding in the commit message. */
    public final int endLine;
    /** The column (0-based) of the end of the finding in the commit message. */
    public final int endCol;

    /** Returns true when {@code elapsedMicros} reflects the current scanner pattern. */
    public boolean isValid() {
      return elapsedMicros >= 0;
    }

    /** A finding for the current scanner pattern with relevant {@code elapsedMicros}. */
    CommitMessageFinding(String commitMsg, String text, String elapsedMicros, int start, int end) {
      this.start = start;
      this.end = end;
      this.text = text;
      this.elapsedMicros = Long.parseLong(elapsedMicros, 16);

      Matcher m = NL.matcher(commitMsg);
      int line = 1;
      int lineStart = 0;
      int startLine = 0;
      int startCol = -1;
      int endLine = 0;
      int endCol = -1;
      while (m.find()) {
        if (m.start() > start) {
          startLine = line;
          startCol = start - lineStart;
        }
        if (m.start() > end) {
          endLine = line;
          endCol = end - lineStart;
          break;
        }
        line++;
        lineStart = m.end();
      }
      if (startLine == 0) {
        startLine = line;
        startCol = start - lineStart;
      }
      if (endLine == 0) {
        endLine = line;
        endCol = end - lineStart;
      }
      this.startLine = startLine;
      this.startCol = startCol;
      this.endLine = endLine;
      this.endCol = endCol;
    }

    /** A finding for a different scanner pattern -- {@code elapsedMicros} not relevant. */
    CommitMessageFinding(String commitMsg, String text, int start, int end) {
      this(commitMsg, text, "-1", start, end);
    }
  }
}
