// 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.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
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.GitReferenceUpdatedListener;
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.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.validators.CommitValidationException;
import com.google.gerrit.server.git.validators.CommitValidationListener;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.AbstractModule;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;

/** Listener to manage configuration for enforcing review of copyright declarations and licenses. */
@Singleton
class CopyrightConfig
    implements CommitValidationListener, RevisionCreatedListener, GitReferenceUpdatedListener {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final long DEFAULT_MAX_ELAPSED_SECONDS = 8;

  private final Metrics metrics;
  private final AllProjectsName allProjectsName;
  private final String pluginName;
  private final GitRepositoryManager repoManager;
  private final ProjectCache projectCache;
  private final PluginConfigFactory pluginConfigFactory;
  private final CopyrightReviewApi reviewApi;

  private PluginConfig gerritConfig;
  private CheckConfig checkConfig;

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

  @Singleton
  private static class Metrics {
    final Timer0 readConfigTimer;
    final Timer0 checkConfigTimer;
    final Timer0 testConfigTimer;

    @Inject
    Metrics(MetricMaker metricMaker) {
      readConfigTimer =
          metricMaker.newTimer(
              "plugins/copyright/read_config_latency",
              new Description("Time spent reading and parsing plugin configurations")
                  .setCumulative()
                  .setUnit(Units.MICROSECONDS));
      checkConfigTimer =
          metricMaker.newTimer(
              "plugins/copyright/check_config_latency",
              new Description("Time spent testing proposed plugin configurations")
                  .setCumulative()
                  .setUnit(Units.MICROSECONDS));
      testConfigTimer =
          metricMaker.newTimer(
              "plugins/copyright/test_config_latency",
              new Description("Time spent testing configurations against difficult file pattern")
                  .setCumulative()
                  .setUnit(Units.MICROSECONDS));
    }
  }

  @Inject
  CopyrightConfig(
      Metrics metrics,
      AllProjectsName allProjectsName,
      @PluginName String pluginName,
      GitRepositoryManager repoManager,
      ProjectCache projectCache,
      PluginConfigFactory pluginConfigFactory,
      CopyrightReviewApi reviewApi)
      throws IOException, ConfigInvalidException {
    this.metrics = metrics;
    this.allProjectsName = allProjectsName;
    this.pluginName = pluginName;
    this.repoManager = repoManager;
    this.projectCache = projectCache;
    this.pluginConfigFactory = pluginConfigFactory;
    this.reviewApi = reviewApi;

    long nanoStart = System.nanoTime();
    try {
      checkConfig = readConfig(projectCache.getAllProjects().getProject().getConfigRefState());
    } finally {
      long elapsedMicros = (System.nanoTime() - nanoStart) / 1000;
      metrics.readConfigTimer.record(elapsedMicros, TimeUnit.MICROSECONDS);
    }
  }

  private CopyrightConfig(
      MetricMaker metricMaker, CopyrightReviewApi reviewApi, String projectConfigContents)
      throws ConfigInvalidException {
    metrics = new Metrics(metricMaker);
    allProjectsName = new AllProjectsName("All-Projects");
    pluginName = "copyright";
    repoManager = null;
    projectCache = null;
    pluginConfigFactory = null;
    this.reviewApi = reviewApi;
    checkConfig = new CheckConfig(pluginName, projectConfigContents);
  }

  @VisibleForTesting
  static CopyrightConfig createTestInstance(
      MetricMaker metricMaker, CopyrightReviewApi reviewApi, String projectConfigContents)
      throws ConfigInvalidException {
    return new CopyrightConfig(metricMaker, reviewApi, projectConfigContents);
  }

  ScannerConfig getScannerConfig() {
    return checkConfig.scannerConfig;
  }

  /** Listens for merges to /refs/meta/config on All-Projects to reload plugin configuration. */
  @Override
  public void onGitReferenceUpdated(GitReferenceUpdatedListener.Event event) {
    if (!event.getRefName().equals(RefNames.REFS_CONFIG)) {
      return;
    }
    if (!event.getProjectName().equals(allProjectsName.get())) {
      return;
    }
    long nanoStart = System.nanoTime();
    try {
      clearConfig();
      checkConfig = readConfig(event.getNewObjectId());
    } catch (IOException | ConfigInvalidException e) {
      logger.atSevere().withCause(e).log("%s plugin unable to load configuration", pluginName);
      checkConfig = null;
      return;
    } finally {
      long elapsedMicros = (System.nanoTime() - nanoStart) / 1000;
      metrics.readConfigTimer.record(elapsedMicros, TimeUnit.MICROSECONDS);
    }
  }

  /** Blocks upload of bad plugin configurations to /refs/meta/config on All-Projects. */
  @Override
  public List<CommitValidationMessage> onCommitReceived(CommitReceivedEvent event)
      throws CommitValidationException {
    if (!event.getBranchNameKey().get().equals(RefNames.REFS_CONFIG)) {
      return Collections.emptyList();
    }
    if (!event.getProjectNameKey().equals(allProjectsName)) {
      return Collections.emptyList();
    }
    long readStart = System.nanoTime();
    long checkStart = -1;
    long elapsedMicros = -1;
    CheckConfig trialConfig = null;
    try {
      trialConfig = readConfig(event.commit.getName());
      elapsedMicros = (System.nanoTime() - readStart) / 1000;
      metrics.readConfigTimer.record(elapsedMicros, TimeUnit.MICROSECONDS);
      if (Objects.equals(trialConfig.scannerConfig, checkConfig.scannerConfig)) {
        return Collections.emptyList();
      }
      checkStart = System.nanoTime();
      long maxElapsedSeconds =
          gerritConfig == null
              ? DEFAULT_MAX_ELAPSED_SECONDS
              : gerritConfig.getLong(ScannerConfig.KEY_TIME_TEST_MAX, DEFAULT_MAX_ELAPSED_SECONDS);
      if (maxElapsedSeconds > 0
          && CheckConfig.hasScanner(trialConfig)
          && !CheckConfig.scannersEqual(trialConfig, checkConfig)) {
        String commitMessage = event.commit.getFullMessage();
        ImmutableList<CopyrightReviewApi.CommitMessageFinding> findings =
            trialConfig.checkCommitMessage(commitMessage);
        if (CheckConfig.mustReportFindings(findings, maxElapsedSeconds)) {
          throw reviewApi.getCommitMessageException(pluginName, findings, maxElapsedSeconds);
        }
      }
      boolean pluginEnabled =
          gerritConfig != null && gerritConfig.getBoolean(ScannerConfig.KEY_ENABLE, false);
      CheckConfig.checkProjectConfig(reviewApi, pluginEnabled, trialConfig);
      return trialConfig == null || trialConfig.scannerConfig == null
          ? Collections.emptyList()
          : trialConfig.scannerConfig.messages;
    } catch (IOException e) {
      logger.atSevere().withCause(e).log(
          "failed to read new project.config for %s plugin", pluginName);
      throw new CommitValidationException("failed to read new project.config", e);
    } catch (ConfigInvalidException e) {
      logger.atSevere().withCause(e).log("unable to parse %s plugin config", pluginName);
      if (trialConfig != null && trialConfig.scannerConfig != null) {
        trialConfig.scannerConfig.messages.add(ScannerConfig.errorMessage(e.getMessage()));
        return trialConfig.scannerConfig.messages;
      } else {
        throw new CommitValidationException("unable to parse new project.config", e);
      }
    } finally {
      if (elapsedMicros < 0) {
        elapsedMicros = (System.nanoTime() - readStart) / 1000;
        metrics.readConfigTimer.record(elapsedMicros, TimeUnit.MICROSECONDS);
      } else if (checkStart >= 0) {
        long elapsedNanos = System.nanoTime() - checkStart;
        metrics.checkConfigTimer.record(elapsedNanos, TimeUnit.NANOSECONDS);
      }
      if (trialConfig != null
          && trialConfig.scannerConfig != null
          && trialConfig.scannerConfig.hasErrors()) {
        StringBuilder sb = new StringBuilder();
        sb.append("\nerror in ");
        sb.append(pluginName);
        sb.append(" plugin configuration");
        trialConfig.scannerConfig.appendMessages(sb);
        throw new CommitValidationException(sb.toString());
      }
    }
  }

  /** Warns on review thread about suspect plugin configurations. */
  @Override
  public void onRevisionCreated(RevisionCreatedListener.Event event) {
    String project = event.getChange().project;
    String branch = event.getChange().branch;

    if (!branch.equals(RefNames.REFS_CONFIG)) {
      return;
    }
    if (!project.equals(allProjectsName.get())) {
      return;
    }
    if (!event.getRevision().files.keySet().contains(ProjectConfig.PROJECT_CONFIG)) {
      return;
    }
    // passed onCommitReceived so expect at worst only warnings here
    long readStart = System.nanoTime();
    long checkStart = -1;
    long elapsedMicros = -1;
    CheckConfig trialConfig = null;
    try {
      trialConfig = readConfig(event.getChange().currentRevision);
      elapsedMicros = (System.nanoTime() - readStart) / 1000;
      metrics.readConfigTimer.record(elapsedMicros, TimeUnit.MICROSECONDS);
      if (Objects.equals(trialConfig, checkConfig.scannerConfig)) {
        return;
      }

      checkStart = System.nanoTime();
      if (CheckConfig.hasScanner(trialConfig)
          && !CheckConfig.scannersEqual(trialConfig, checkConfig)) {
        long maxElapsedSeconds =
            gerritConfig == null
                ? DEFAULT_MAX_ELAPSED_SECONDS
                : gerritConfig.getLong(
                    ScannerConfig.KEY_TIME_TEST_MAX, DEFAULT_MAX_ELAPSED_SECONDS);
        if (maxElapsedSeconds > 0) {
          String commitMessage = event.getRevision().commitWithFooters;
          ImmutableList<CopyrightReviewApi.CommitMessageFinding> findings =
              trialConfig.checkCommitMessage(commitMessage);
          ReviewResult result =
              reviewApi.reportCommitMessageFindings(
                  pluginName,
                  allProjectsName.get(),
                  checkConfig == null ? null : checkConfig.scannerConfig,
                  trialConfig.scannerConfig,
                  event,
                  findings,
                  maxElapsedSeconds);
          logReviewResultErrors(event, result);
        }
      }
      boolean pluginEnabled =
          gerritConfig != null && gerritConfig.getBoolean(ScannerConfig.KEY_ENABLE, false);
      CheckConfig.checkProjectConfig(reviewApi, pluginEnabled, trialConfig);
      return;
    } catch (RestApiException | ConfigInvalidException | IOException e) {
      logger.atSevere().withCause(e).log("%s plugin unable to read new configuration", pluginName);
      // throw IllegalStateException? RestApiException?
      return;
    } finally {
      if (trialConfig != null
          && trialConfig.scannerConfig != null
          && !trialConfig.scannerConfig.messages.isEmpty()
          && !trialConfig.scannerConfig.hasErrors()) {
        try {
          ReviewResult result =
              reviewApi.reportConfigMessages(
                  pluginName,
                  project,
                  ProjectConfig.PROJECT_CONFIG,
                  checkConfig.scannerConfig,
                  trialConfig.scannerConfig,
                  event);
          logReviewResultErrors(event, result);
        } catch (RestApiException e) {
          logger.atSevere().withCause(e).log(
              "%s plugin unable to read new configuration", pluginName);
          // throw IllegalStateException? RestApiException?
          return;
        }
      }
      if (elapsedMicros < 0) {
        elapsedMicros = (System.nanoTime() - readStart) / 1000;
        metrics.readConfigTimer.record(elapsedMicros, TimeUnit.MICROSECONDS);
      } else if (checkStart >= 0) {
        long elapsedNanos = System.nanoTime() - checkStart;
        metrics.checkConfigTimer.record(elapsedNanos, TimeUnit.NANOSECONDS);
      }
    }
  }

  /** Returns true if copyright validation enabled for {@code project}. */
  boolean isProjectEnabled(ScannerConfig scannerConfig, String project) {
    // scan all projects when missing
    if (!scannerConfig.matchProjects.isEmpty()
        && !ScannerConfig.matchesAny(project, scannerConfig.matchProjects)) {
      // doesn't match == isn't checked
      return false;
    }
    // exclude no projects when missing
    if (!scannerConfig.excludeProjects.isEmpty()
        && ScannerConfig.matchesAny(project, scannerConfig.excludeProjects)) {
      // does match == isn't checked
      return false;
    }
    ProjectState projectState;
    try {
      projectState = projectCache.checkedGet(new Project.NameKey(project));
    } catch (IOException e) {
      logger.atSevere().withCause(e).log("error getting project state of %s", project);
      // throw IllegalStateException? RestApiException?
      return scannerConfig.defaultEnable;
    }
    if (projectState == null) {
      logger.atSevere().log("error getting project state of %s", project);
      // throw IllegalStateException? RestApiException?
      return scannerConfig.defaultEnable;
    }
    ProjectConfig projectConfig = projectState.getConfig();
    if (projectConfig == null) {
      logger.atWarning().log("error getting project config of %s", project);
      // throw IllegalStateException? RestApiException? return?
      return scannerConfig.defaultEnable;
    }
    PluginConfig pluginConfig = projectConfig.getPluginConfig(pluginName);
    if (pluginConfig == null) {
      // no plugin config section in project so use default
      return scannerConfig.defaultEnable;
    }
    return pluginConfig.getBoolean(ScannerConfig.KEY_ENABLE, scannerConfig.defaultEnable);
  }

  /**
   * Loads and compiles configured patterns from {@code ref/meta/All-Projects/project.config} and
   * {@code gerrit.config}.
   *
   * @param projectConfigObjectId identifies the version of project.config to load and to compile
   * @return the new scanner configuration to check
   * @throws IOException if accessing the repository fails
   */
  private CheckConfig readConfig(String projectConfigObjectId)
      throws IOException, ConfigInvalidException {
    CheckConfig checkConfig = null;
    // new All-Projects project.config not yet in cache -- read from repository
    ObjectId id = ObjectId.fromString(projectConfigObjectId);
    if (ObjectId.zeroId().equals(id)) {
      return checkConfig;
    }
    try (Repository repo = repoManager.openRepository(allProjectsName)) {
      checkConfig =
          new CheckConfig(pluginName, readFileContents(repo, id, ProjectConfig.PROJECT_CONFIG));
    }
    gerritConfig = pluginConfigFactory.getFromGerritConfig(pluginName, true);
    if (gerritConfig == null) {
      // throw IllegalStateException? RestApiException?
      checkConfig.scannerConfig.messages.add(
          ScannerConfig.hintMessage(
              "missing [plugin \"" + pluginName + "\"] section in gerrit.config"));
    } else {
      checkConfig.scannerConfig.defaultEnable =
          gerritConfig.getBoolean(ScannerConfig.KEY_ENABLE, false);
    }
    return checkConfig;
  }

  /** Erases any prior configuration state. */
  private void clearConfig() {
    checkConfig = null;
  }

  private void logReviewResultErrors(RevisionCreatedListener.Event event, ReviewResult result) {
    if (!Strings.isNullOrEmpty(result.error)) {
      logger.atSevere().log(
          "%s plugin revision %s: error posting review: %s",
          pluginName, event.getChange().currentRevision, result.error);
    }
    for (Map.Entry<String, AddReviewerResult> entry : result.reviewers.entrySet()) {
      AddReviewerResult arr = entry.getValue();
      if (!Strings.isNullOrEmpty(arr.error)) {
        logger.atSevere().log(
            "%s plugin revision %s: error adding reviewer %s: %s",
            pluginName, event.getChange().currentRevision, entry.getKey(), arr.error);
      }
    }
  }

  private String readFileContents(Repository repo, ObjectId objectId, String filename)
      throws IOException {
    RevWalk rw = new RevWalk(repo);
    RevTree tree = rw.parseTree(objectId);
    try (TreeWalk tw = TreeWalk.forPath(rw.getObjectReader(), filename, tree)) {
      ObjectLoader loader = repo.open(tw.getObjectId(0), Constants.OBJ_BLOB);
      return new String(loader.getCachedBytes(), UTF_8);
    }
  }
}
