// Copyright (C) 2016 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.supermanifest;

import static com.google.gerrit.entities.RefNames.REFS_HEADS;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.errorprone.annotations.FormatMethod;
import com.google.errorprone.annotations.FormatString;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.api.projects.BranchInput;
import com.google.gerrit.extensions.config.DownloadScheme;
import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.PreconditionFailedException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.metrics.Counter1;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Field;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.logging.PluginMetadata;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.plugincontext.PluginMapContext;
import com.google.gerrit.server.project.BranchResource;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.errors.RevisionSyntaxException;
import org.eclipse.jgit.gitrepo.RepoCommand;
import org.eclipse.jgit.gitrepo.RepoCommand.RemoteFile;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.TreeWalk;

/**
 * This plugin will listen for changes to XML files in manifest repositories. When it finds such
 * changes, it will trigger an update of the associated superproject.
 */
@Singleton
public class SuperManifestRefUpdatedListener
    implements GitReferenceUpdatedListener,
        LifecycleListener,
        RestModifyView<BranchResource, BranchInput> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final SuperManifestRepoManager.Factory repoManagerFactory;
  private final URI canonicalWebUrl;
  private final PluginConfigFactory cfgFactory;
  private final String pluginName;
  private final AllProjectsName allProjectsName;
  private final ProjectCache projectCache;
  private final Provider<PersonIdent> serverIdent;
  private final Provider<IdentifiedUser> identifiedUser;
  private final PermissionBackend permissionBackend;
  private final PluginMapContext<DownloadScheme> downloadScheme;
  private final Counter1<String> manifestUpdateResultCounter;
  private final Timer1<ConfigEntry.ToolType> superprojectCommitTimer;

  // Mutable.
  private AtomicReference<ImmutableSet<ConfigEntry>> config = new AtomicReference<>();

  @Inject
  SuperManifestRefUpdatedListener(
      AllProjectsName allProjectsName,
      @CanonicalWebUrl String canonicalWebUrl,
      @PluginName String pluginName,
      PluginMapContext<DownloadScheme> downloadScheme,
      PluginConfigFactory cfgFactory,
      ProjectCache projectCache,
      @GerritPersonIdent Provider<PersonIdent> serverIdent,
      SuperManifestRepoManager.Factory repoManagerFactory,
      Provider<IdentifiedUser> identifiedUser,
      PermissionBackend permissionBackend,
      MetricMaker metrics) {

    this.pluginName = pluginName;
    this.serverIdent = serverIdent;
    this.allProjectsName = allProjectsName;
    this.repoManagerFactory = repoManagerFactory;
    try {
      this.canonicalWebUrl = new URI(canonicalWebUrl);
    } catch (URISyntaxException e) {
      throw new IllegalArgumentException(e);
    }

    this.downloadScheme = downloadScheme;
    this.cfgFactory = cfgFactory;
    this.projectCache = projectCache;
    this.identifiedUser = identifiedUser;
    this.permissionBackend = permissionBackend;
    this.manifestUpdateResultCounter =
        metrics.newCounter(
            "supermanifest/update_result",
            new Description(
                "Result of a manifest update for a specific conf (all conf parsed fine)"),
            Field.ofString(
                    "result",
                    (metadataBuilder, fieldValue) ->
                        metadataBuilder
                            .pluginName("supermanifest")
                            .addPluginMetadata(PluginMetadata.create("update_result", fieldValue)))
                .description("result of a manifest update")
                .build());
    this.superprojectCommitTimer =
        metrics.newTimer(
            "supermanifest/superproject_commit_latency",
            new Description("Time taken to parse the manifest and update the superproject"),
            Field.ofEnum(
                    ConfigEntry.ToolType.class,
                    "tool",
                    (metadataBuilder, fieldValue) ->
                        metadataBuilder
                            .pluginName("supermanifest")
                            .addPluginMetadata(PluginMetadata.create("tool", fieldValue)))
                .description("Tool handling the manifest (repo or jiri)")
                .build());
  }

  @FormatMethod
  private void warn(@FormatString String formatStr, Object... args) {
    logger.atWarning().log("%s: %s", canonicalWebUrl, String.format(formatStr, args));
  }

  @FormatMethod
  private void error(@FormatString String formatStr, Object... args) {
    logger.atSevere().log("%s: %s", canonicalWebUrl, String.format(formatStr, args));
  }

  @FormatMethod
  private void errorWithCause(Exception e, @FormatString String formatStr, Object... args) {
    logger.atSevere().withCause(e).log("%s: %s", canonicalWebUrl, String.format(formatStr, args));
  }

  @FormatMethod
  private void info(@FormatString String formatStr, Object... args) {
    logger.atInfo().log("%s: %s", canonicalWebUrl, String.format(formatStr, args));
  }

  /*
     [superproject "submodules:refs/heads/nyc"]
        srcRepo = platforms/manifest
        srcRef = refs/heads/nyc
        srcPath = manifest.xml
  */
  private Set<ConfigEntry> parseConfiguration(PluginConfigFactory cfgFactory, String name)
      throws NoSuchProjectException {
    Config cfg = cfgFactory.getProjectPluginConfig(allProjectsName, name);

    Set<ConfigEntry> newConf = new HashSet<>();
    Set<String> destinations = new HashSet<>();
    Set<String> wildcardDestinations = new HashSet<>();
    Set<String> sources = new HashSet<>();

    for (String sect : cfg.getSections()) {
      if (!sect.equals(ConfigEntry.SECTION_NAME)) {
        warn("%s.config: ignoring invalid section %s", name, sect);
      }
    }
    for (String subsect : cfg.getSubsections(ConfigEntry.SECTION_NAME)) {
      try {
        ConfigEntry configEntry = new ConfigEntry(cfg, subsect);
        if (destinations.contains(configEntry.srcRepoKey.get())
            || sources.contains(configEntry.destRepoKey.get())) {
          // Don't want cyclic dependencies.
          throw new ConfigInvalidException(
              String.format("repo in entry %s cannot be both source and destination", configEntry));
        }
        if (configEntry.destBranch.equals("*")) {
          if (wildcardDestinations.contains(configEntry.destRepoKey.get())) {
            throw new ConfigInvalidException(
                String.format(
                    "repo %s already has a wildcard destination branch.", configEntry.destRepoKey));
          }
          wildcardDestinations.add(configEntry.destRepoKey.get());
        }

        sources.add(configEntry.srcRepoKey.get());
        destinations.add(configEntry.destRepoKey.get());

        newConf.add(configEntry);

      } catch (ConfigInvalidException e) {
        error("invalid configuration: %s", e);
      }
    }

    return newConf;
  }

  private boolean checkRepoExists(Project.NameKey id) {
    return projectCache.get(id) != null;
  }

  @Override
  public void stop() {}

  @Override
  public void start() {
    try {
      updateConfiguration();
    } catch (NoSuchProjectException e) {
      warn("can't read configuration: %s", e.getMessage());
    }
  }

  /** for debugging. */
  private String configurationToString() {
    Set<ConfigEntry> cfg = config.get();
    if (cfg == null) {
      return "No config loaded (could not read All-Projects)";
    }
    StringBuilder b = new StringBuilder();
    b.append("Supermanifest config (").append(cfg.size()).append(") {\n");
    for (ConfigEntry c : cfg) {
      b.append(" ").append(c).append("\n");
    }
    b.append("}\n");
    return b.toString();
  }

  private void updateConfiguration() throws NoSuchProjectException {
    Set<ConfigEntry> entries = parseConfiguration(cfgFactory, pluginName);

    Set<ConfigEntry> filtered = new HashSet<>();
    for (ConfigEntry e : entries) {
      if (!checkRepoExists(e.srcRepoKey)) {
        error("source repo '%s' does not exist", e.srcRepoKey);
      } else if (!checkRepoExists(e.destRepoKey)) {
        error("destination repo '%s' does not exist", e.destRepoKey);
      } else {
        filtered.add(e);
      }
    }

    config.set(ImmutableSet.copyOf(filtered));
  }

  @Override
  public void onGitReferenceUpdated(Event event) {
    if (event.getProjectName().equals(allProjectsName.get())) {
      if (event.getRefName().equals("refs/meta/config")) {
        try {
          // TODO: Remove, this is just band-aid.
          // Evict project cache because this is called before that eviction is done in core
          projectCache.evict(allProjectsName);
          updateConfiguration();
        } catch (NoSuchProjectException e) {
          throw new IllegalStateException(e);
        }
      }
      return;
    }
    if (RefNames.isNoteDbMetaRef(event.getRefName())) {
      // NoteDb meta ref updates never cause supermanifest updates.
      return;
    }

    List<ConfigEntry> relevantConfigs =
        findRelevantConfigs(event.getProjectName(), event.getRefName());
    for (ConfigEntry relevantConfig : relevantConfigs) {
      try {
        updateForConfig(relevantConfig, event.getRefName());
      } catch (ConfigInvalidException | IOException | GitAPIException e) {
        // We only want the trace up to here. We could recurse into the exception, but this at least
        // trims the very common jgit.gitrepo.RepoCommand.RemoteUnavailableException.
        StackTraceElement here = Thread.currentThread().getStackTrace()[1];
        e.setStackTrace(trimStack(e.getStackTrace(), here));

        // We are in an asynchronously called listener, so there is no user action to give
        // feedback to. We log the error, but it would be nice if we could surface these logs
        // somewhere.  Perhaps we could store these as commits in some special branch (but in
        // what repo?).
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        error(
            "update for %s (ref %s) failed: %s", relevantConfig.toString(), event.getRefName(), sw);
      }
    }
  }

  @Override
  public Response<?> apply(BranchResource resource, BranchInput input)
      throws AuthException, PermissionBackendException, PreconditionFailedException {
    permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
    String manifestProject = resource.getBranchKey().project().get();
    String manifestBranch = resource.getBranchKey().branch();
    info(
        "manual trigger for %s:%s by %d. Config: %s",
        manifestProject,
        manifestBranch,
        identifiedUser.get().getAccountId().get(),
        configurationToString());

    if (config.get() == null) {
      error(
          "Plugin could not read conf from All-Projects (processing %s:%s)",
          manifestProject, manifestBranch);
      throw new PreconditionFailedException("Plugin could not read conf from All-Projects");
    }

    List<ConfigEntry> relevantConfigs =
        findRelevantConfigs(resource.getProjectState().getProject().getName(), resource.getRef());
    if (relevantConfigs.isEmpty()) {
      info(
          "manual trigger for %s:%s: no configs found, nothing to do.",
          manifestProject, manifestBranch);
      return Response.none();
    }
    for (ConfigEntry config : relevantConfigs) {
      try {
        updateForConfig(config, resource.getRef());
      } catch (ConfigInvalidException e) {
        errorWithCause(e, "Invalid conf processing %s:%s", manifestProject, manifestBranch);
        throw new PreconditionFailedException(e.getMessage());
      } catch (GitAPIException | IOException e) {
        errorWithCause(e, "Internal error processing %s:%s", manifestProject, manifestBranch);
        return Response.withStatusCode(500, "Internal error: " + e.getMessage());
      }
    }
    return Response.ok();
  }

  private List<ConfigEntry> findRelevantConfigs(String project, String refName) {
    Set<ConfigEntry> cfg = config.get();
    List<ConfigEntry> relevantConfigs = new ArrayList<>();
    if (cfg == null) {
      return relevantConfigs;
    }
    for (ConfigEntry c : cfg) {
      if (!c.srcRepoKey.get().equals(project)) {
        continue;
      }

      if (!(c.destBranch.equals("*") || c.srcRef.equals(refName))) {
        continue;
      }

      if (c.destBranch.equals("*") && !refName.startsWith(REFS_HEADS)) {
        continue;
      }

      if (c.srcRefsExcluded.contains(refName)) {
        continue;
      }
      relevantConfigs.add(c);
    }
    return relevantConfigs;
  }

  private void updateForConfig(ConfigEntry c, String refName)
      throws ConfigInvalidException, IOException, GitAPIException {
    SubModuleUpdater subModuleUpdater;
    switch (c.getToolType()) {
      case Repo:
        subModuleUpdater = new RepoUpdater(serverIdent.get());
        break;
      case Jiri:
        subModuleUpdater = new JiriUpdater(serverIdent.get(), canonicalWebUrl, downloadScheme);
        break;
      default:
        throw new ConfigInvalidException(
            String.format("invalid toolType: %s", c.getToolType().name()));
    }

    String status = "NOT_ATTEMPTED";
    try (GerritRemoteReader reader =
            new GerritRemoteReader(repoManagerFactory.create(c), canonicalWebUrl.toString());
        Timer1.Context<ConfigEntry.ToolType> ignored = superprojectCommitTimer.start(c.toolType)) {
      subModuleUpdater.update(reader, c, refName);
      status = "OK";
    } catch (ConcurrentRefUpdateException e) {
      status = "LOCK_FAILURE";
      throw e;
    } catch (ConfigInvalidException e) {
      status = "INVALID_SUBMODULE_CONFIGURATION";
      throw e;
    } catch (GitAPIException e) {
      status = "INTERNAL";
      throw e;
    } catch (IOException e) {
      status = "IO_ERROR";
      throw e;
    } finally {
      manifestUpdateResultCounter.increment(status);
    }
  }

  /**
   * Remove boring stack frames. This retains the innermost frames up to and including the {@code
   * class#method} passed in {@code ref}.
   */
  @VisibleForTesting
  static StackTraceElement[] trimStack(StackTraceElement[] trace, StackTraceElement ref) {
    List<StackTraceElement> trimmed = new ArrayList<>();
    for (StackTraceElement e : trace) {
      trimmed.add(e);
      if (e.getClassName().equals(ref.getClassName())
          && e.getMethodName().equals(ref.getMethodName())) {
        break;
      }
    }

    return trimmed.toArray(new StackTraceElement[trimmed.size()]);
  }

  // GerritRemoteReader is for injecting Gerrit's Git implementation into JGit.
  static class GerritRemoteReader implements RepoCommand.RemoteReader, AutoCloseable {
    private static final FluentLogger logger = FluentLogger.forEnclosingClass();
    private final String canonicalWebUrl;
    private final SuperManifestRepoManager repoManager;

    GerritRemoteReader(
        SuperManifestRepoManager repoManager, @CanonicalWebUrl String canonicalWebUrl) {
      this.repoManager = repoManager;
      this.canonicalWebUrl = canonicalWebUrl;
    }

    @Override
    public ObjectId sha1(String uriStr, String refName) throws GitAPIException {
      // This is a (mis)feature of JGit, which ignores SHA1s but only if ignoreRemoteFailures
      // is set.
      if (ObjectId.isId(refName)) {
        return ObjectId.fromString(refName);
      }

      try {
        // When the remote is fetch="<relative path>" the manifest parser uses a repoName as URI.
        // Do a poor man's guessing if we have a repoName or URI
        Repository repo =
            uriStr.contains("://")
                ? repoManager.openByUri(uriStr)
                : repoManager.openByName(Project.nameKey(uriStr));
        Ref ref = repo.findRef(refName);
        if (ref == null || ref.getObjectId() == null) {
          logger.atWarning().log(
              "%s: in repo %s: cannot resolve ref %s", canonicalWebUrl, uriStr, refName);
          return null;
        }

        ref = repo.getRefDatabase().peel(ref);
        ObjectId id = ref.getPeeledObjectId();
        return id != null ? id : ref.getObjectId();
      } catch (RepositoryNotFoundException e) {
        logger.atWarning().withCause(e).log(
            "%s: failed to open repository %s", canonicalWebUrl, uriStr);
        return null;
      } catch (IOException io) {
        RefNotFoundException e =
            new RefNotFoundException(String.format("cannot open %s to read %s", uriStr, refName));
        e.initCause(io);
        throw e;
      }
    }

    @Override
    public RemoteFile readFileWithMode(String uriStr, String ref, String path)
        throws GitAPIException, IOException {
      // When the remote is fetch="<relative path>" the manifest parser uses a repoName as URI.
      // Do a poor man's guessing if we have a repoName or URI
      Repository repo =
          uriStr.contains("://")
              ? repoManager.openByUri(uriStr)
              : repoManager.openByName(Project.nameKey(uriStr));
      Ref r = repo.findRef(ref);
      ObjectId objectId = r == null ? repo.resolve(ref) : r.getObjectId();
      if (objectId == null) {
        throw new RevisionSyntaxException(
            String.format("repo %s does not have ref %s", repo.toString(), ref), ref);
      }
      RevCommit commit = repo.parseCommit(objectId);
      TreeWalk tw = TreeWalk.forPath(repo, path, commit.getTree());
      return new RemoteFile(
          tw.getObjectReader().open(tw.getObjectId(0)).getCachedBytes(Integer.MAX_VALUE),
          tw.getFileMode(0));
    }

    public Repository openRepository(String name) throws IOException {
      return repoManager.openByName(Project.nameKey(name));
    }

    @Override
    public void close() {
      try {
        repoManager.close();
      } catch (Exception e) {
        logger.atWarning().withCause(e).log("Error closing the repoManager");
      }
    }
  }

  // AutoCloseable so implementations can keep a cache
  public interface SuperManifestRepoManager extends AutoCloseable {
    Repository openByUri(String uriStr) throws IOException;

    Repository openByName(Project.NameKey repoName) throws IOException;

    interface Factory {
      SuperManifestRepoManager create(ConfigEntry c);
    }
  }

  static class GerritSuperManifestRepoManager implements SuperManifestRepoManager {
    private final HashMap<Project.NameKey, Repository> repos;
    private final GitRepositoryManager repoManager;
    private final String canonicalWebUrl;

    @Inject
    GerritSuperManifestRepoManager(
        GitRepositoryManager repoManager,
        @CanonicalWebUrl String canonicalWebUrl,
        @Assisted ConfigEntry e) {
      // Add ConfigEntry (even when this implementation doesn't need it) so
      // injection can bind the factory automatically
      this.repos = new HashMap<>();
      this.repoManager = repoManager;
      this.canonicalWebUrl = canonicalWebUrl;
    }

    @Override
    public Repository openByName(Project.NameKey name) throws IOException {
      if (repos.containsKey(name)) {
        return repos.get(name);
      }

      Repository repo = repoManager.openRepository(name);
      repos.put(name, repo);
      return repo;
    }

    @Override
    public Repository openByUri(String uriStr) throws IOException {
      // A URL in this host is <canonicalWebUrl>/<repoName>.
      //
      // In googlesource the canonicalWebUrl is xxxx-review.googlesource.com and
      // the repos are xxx.googlesource.com. Keep taking the path for backwards compatibility and
      // clean it up when googlesource does the right thing.
      String repoName;
      if (uriStr.startsWith(canonicalWebUrl)) {
        repoName = uriStr.substring(canonicalWebUrl.length());
      } else {
        logger.atWarning().log(
            "%s: taking path from %s that looks from another host", canonicalWebUrl, uriStr);
        URI uri;
        try {
          uri = new URI(uriStr);
        } catch (URISyntaxException e) {
          throw new RepositoryNotFoundException("Cannot parse uri: " + uriStr);
        }

        repoName = uri.getPath();
      }

      while (repoName.startsWith("/")) {
        repoName = repoName.substring(1);
      }

      return openByName(Project.nameKey(repoName));
    }

    @Override
    public void close() {
      for (Repository repo : repos.values()) {
        repo.close();
      }
      repos.clear();
    }
  }
}
