// 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.CopyrightReviewApi.ALWAYS_REVIEW;
import static com.googlesource.gerrit.plugins.copyright.ScannerConfig.KEY_ENABLE;

import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.api.changes.AddReviewerResult;
import com.google.gerrit.extensions.api.changes.ReviewResult;
import com.google.gerrit.extensions.events.RevisionCreatedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
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.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.AbstractModule;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.copyright.lib.CopyrightScanner.Match;
import com.googlesource.gerrit.plugins.copyright.lib.IndexedLineReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.ObjectStream;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.TreeFilter;

/** Listener to enforce review of copyright declarations and licenses. */
public class CopyrightValidator implements RevisionCreatedListener {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final String pluginName; // name of plugin as installed in gerrit
  private final Metrics metrics;
  private final GitRepositoryManager repoManager;
  private final PluginConfigFactory pluginConfigFactory;
  private final CopyrightReviewApi reviewApi;

  private CopyrightConfig copyrightConfig;
  private ScannerConfig scannerConfig; // configuration state for plugin

  static AbstractModule module() {
    return new AbstractModule() {
      @Override
      protected void configure() {
        DynamicSet.bind(binder(), RevisionCreatedListener.class).to(CopyrightValidator.class);
      }
    };
  }

  @Singleton
  private static class Metrics {
    final Counter0 scanCount;
    final Timer0 scanRevisionTimer;
    final Timer0 scanFileTimer;
    final Counter1 scanCountByProject;
    final Timer1 scanRevisionTimerByProject;
    final Timer1 scanFileTimerByProject;
    final Counter1 scanCountByBranch;
    final Timer1 scanRevisionTimerByBranch;
    final Timer1 scanFileTimerByBranch;

    @Inject
    Metrics(MetricMaker metricMaker) {
      Field<String> project = Field.ofString("project", "project name");
      Field<String> branch = Field.ofString("branch", "branch name");
      scanCount =
          metricMaker.newCounter(
              "scan_count",
              new Description("Total number of copyright scans").setRate().setUnit("scans"));
      scanRevisionTimer =
          metricMaker.newTimer(
              "scan_revision_latency",
              new Description("Time spent scanning entire revisions")
                  .setCumulative()
                  .setUnit(Units.MILLISECONDS));
      scanFileTimer =
          metricMaker.newTimer(
              "scan_file_latency",
              new Description("Time spent scanning each file")
                  .setCumulative()
                  .setUnit(Units.MICROSECONDS));
      scanCountByProject =
          metricMaker.newCounter(
              "scan_count_by_project",
              new Description("Total number of copyright scans").setRate().setUnit("scans"),
              project);
      scanRevisionTimerByProject =
          metricMaker.newTimer(
              "scan_revision_latency_by_project",
              new Description("Time spent scanning entire revisions")
                  .setCumulative()
                  .setUnit(Units.MILLISECONDS),
              project);
      scanFileTimerByProject =
          metricMaker.newTimer(
              "scan_file_latency_by_project",
              new Description("Time spent scanning each file")
                  .setCumulative()
                  .setUnit(Units.MICROSECONDS),
              project);
      scanCountByBranch =
          metricMaker.newCounter(
              "scan_count_by_branch",
              new Description("Total number of copyright scans").setRate().setUnit("scans"),
              branch);
      scanRevisionTimerByBranch =
          metricMaker.newTimer(
              "scan_revision_latency_by_branch",
              new Description("Time spent scanning entire revisions")
                  .setCumulative()
                  .setUnit(Units.MILLISECONDS),
              branch);
      scanFileTimerByBranch =
          metricMaker.newTimer(
              "scan_file_latency_by_branch",
              new Description("Time spent scanning each file")
                  .setCumulative()
                  .setUnit(Units.MICROSECONDS),
              branch);
    }
  }

  @Inject
  CopyrightValidator(
      Metrics metrics,
      @PluginName String pluginName,
      GitRepositoryManager repoManager,
      CopyrightConfig copyrightConfig,
      @Nullable ScannerConfig scannerConfig,
      PluginConfigFactory pluginConfigFactory,
      CopyrightReviewApi reviewApi) {
    this.metrics = metrics;
    this.pluginName = pluginName;
    this.repoManager = repoManager;
    this.copyrightConfig = copyrightConfig;
    this.scannerConfig = scannerConfig;
    this.pluginConfigFactory = pluginConfigFactory;
    this.reviewApi = reviewApi;
  }

  @Override
  public void onRevisionCreated(RevisionCreatedListener.Event event) {
    String project = event.getChange().project;
    String branch = event.getChange().branch;

    if (branch.startsWith(RefNames.REFS)) {
      // do not scan refs
      return;
    }
    PluginConfig gerritConfig = pluginConfigFactory.getFromGerritConfig(pluginName, true);
    if (gerritConfig == null || !gerritConfig.getBoolean(KEY_ENABLE, false)) {
      logger.atFine().log("copyright plugin not enbled");
      return;
    }
    if (scannerConfig == null) {
      // error already reported during configuration load
      logger.atWarning().log(
          "%s plugin enabled with no configuration -- not scanning revision %s",
          pluginName, event.getChange().currentRevision);
      return;
    }
    if (scannerConfig.scanner == null) {
      if (scannerConfig.hasErrors()) {
        // error already reported during configuration load
        logger.atWarning().log(
            "%s plugin enabled with errors in configuration -- not scanning revision %s",
            pluginName, event.getChange().currentRevision);
      } // else plugin not enabled
      return;
    }
    // allow project override of All-Projects to enable or disable
    if (!copyrightConfig.isProjectEnabled(scannerConfig, project)) {
      return;
    }
    try {
      scanRevision(project, branch, event);
    } catch (IOException | RestApiException e) {
      logger.atSevere().withCause(e).log(
          "%s plugin cannot scan revision %s", pluginName, event.getChange().currentRevision);
      return;
    }
  }

  /**
   * Scans a pushed revision reporting all findings on its review thread.
   *
   * @param project the project or repository to which the change was pushed
   * @param branch the branch the change updates
   * @param event describes the newly created revision triggering the scan
   * @throws IOException if an error occurred reading the repository
   * @throws RestApiException if an error occured reporting findings to the review thread
   */
  private void scanRevision(String project, String branch, RevisionCreatedListener.Event event)
      throws IOException, RestApiException {
    Map<String, ImmutableList<Match>> findings = new HashMap<>();
    ArrayList<String> containedPaths = new ArrayList<>();
    long scanStart = System.nanoTime();
    metrics.scanCount.increment();
    metrics.scanCountByProject.increment(project);
    metrics.scanCountByBranch.increment(branch);

    try (Repository repo = repoManager.openRepository(Project.nameKey(project));
        RevWalk revWalk = new RevWalk(repo);
        TreeWalk tw = new TreeWalk(revWalk.getObjectReader())) {
      RevCommit commit = repo.parseCommit(ObjectId.fromString(event.getRevision().commit.commit));
      tw.setRecursive(true);
      tw.setFilter(TreeFilter.ANY_DIFF);
      tw.addTree(commit.getTree());
      if (commit.getParentCount() > 0) {
        for (RevCommit p : commit.getParents()) {
          if (p.getTree() == null) {
            revWalk.parseHeaders(p);
          }
          tw.addTree(p.getTree());
        }
      }
      while (tw.next()) {
        containedPaths.add(tw.getPathString());
        String fullPath = project + "/" + tw.getPathString();
        if (scannerConfig.isAlwaysReviewPath(fullPath)) {
          findings.put(tw.getPathString(), ALWAYS_REVIEW);
          continue;
        }
        if (!FileMode.EXECUTABLE_FILE.equals(tw.getFileMode())
            && !FileMode.REGULAR_FILE.equals(tw.getFileMode())) {
          continue;
        }
        long fileStart = System.nanoTime();
        try (ObjectReader reader = tw.getObjectReader();
            ObjectStream stream = reader.open(tw.getObjectId(0)).openStream()) {
          IndexedLineReader lineReader = new IndexedLineReader(fullPath, -1, stream);
          ImmutableList<Match> matches =
              scannerConfig.scanner.findMatches(fullPath, -1, lineReader);
          if (!matches.isEmpty()) {
            findings.put(tw.getPathString(), matches);
          }
          long fileTime = (System.nanoTime() - fileStart) / 1000;
          metrics.scanFileTimer.record(fileTime, TimeUnit.MICROSECONDS);
          metrics.scanFileTimerByProject.record(project, fileTime, TimeUnit.MICROSECONDS);
          metrics.scanFileTimerByBranch.record(branch, fileTime, TimeUnit.MICROSECONDS);
        }
      }
    }
    long scanTime = (System.nanoTime() - scanStart) / 1000000;
    metrics.scanRevisionTimer.record(scanTime, TimeUnit.MILLISECONDS);
    metrics.scanRevisionTimerByProject.record(project, scanTime, TimeUnit.MILLISECONDS);
    metrics.scanRevisionTimerByBranch.record(branch, scanTime, TimeUnit.MILLISECONDS);

    ReviewResult result = reviewApi.reportScanFindings(project, scannerConfig, event, findings);
    if (result != null && result.error != null && !result.error.equals("")) {
      logger.atSevere().log(
          "%s plugin revision %s: error posting review: %s",
          pluginName, event.getChange().currentRevision, result.error);
    }
    if (result != null && result.reviewers != null) {
      for (Map.Entry<String, AddReviewerResult> entry : result.reviewers.entrySet()) {
        AddReviewerResult arr = entry.getValue();
        if (arr.error != null && !arr.error.equals("")) {
          logger.atSevere().log(
              "%s plugin revision %s: error adding reviewer %s: %s",
              pluginName, event.getChange().currentRevision, entry.getKey(), arr.error);
        }
      }
    }
  }
}
