// Copyright (C) 2020 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.google.gerrit.plugins.codeowners.backend;

import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.PLUGIN;
import static java.util.Objects.requireNonNull;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics;
import com.google.gerrit.plugins.codeowners.util.JgitPath;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.git.meta.VersionedMetaData;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;

/**
 * A representation of a code owner config that is stored as an {@code OWNERS} file in a source
 * branch.
 *
 * <p>For reading code owner configs or creating/updating them, refer to {@link Factory#load(String,
 * CodeOwnerConfigParser, RevWalk, ObjectId, CodeOwnerConfig.Key)} and {@link
 * Factory#loadCurrent(String, CodeOwnerConfigParser, Repository, CodeOwnerConfig.Key)}.
 *
 * <p><strong>Note:</strong> Any modification (code owner config creation or update) only becomes
 * permanent (and hence written to repository) if {@link
 * #commit(com.google.gerrit.server.git.meta.MetaDataUpdate)} is called.
 */
@VisibleForTesting
public class CodeOwnerConfigFile extends VersionedMetaData {
  public static class Factory {
    private final CodeOwnerMetrics codeOwnerMetrics;

    @Inject
    Factory(CodeOwnerMetrics codeOwnerMetrics) {
      this.codeOwnerMetrics = codeOwnerMetrics;
    }

    /**
     * Creates a {@link CodeOwnerConfigFile} for a code owner config.
     *
     * <p>The code owner config is automatically loaded within this method and can be accessed via
     * {@link #getLoadedCodeOwnerConfig()}.
     *
     * <p>It's safe to call this method for non-existing code owner configs. In that case, {@link
     * #getLoadedCodeOwnerConfig()} won't return any code owner config. Thus, the existence of a
     * code owner config can be easily tested.
     *
     * <p>The code owner config represented by the returned {@link CodeOwnerConfigFile} can be
     * created/updated by setting an {@link CodeOwnerConfigUpdate} via {@link
     * #setCodeOwnerConfigUpdate(CodeOwnerConfigUpdate)} and committing the {@link
     * CodeOwnerConfigUpdate} via {@link #commit(com.google.gerrit.server.git.meta.MetaDataUpdate)}.
     *
     * @param defaultFileName the name of the code owner configuration files that should be used if
     *     none is specified in the code owner config key
     * @param codeOwnerConfigParser the parser that should be used to parse code owner config files
     * @param revWalk the revWalk that should be used to load the revision
     * @param revision the branch revision from which the code owner config file should be loaded
     * @param codeOwnerConfigKey the key of the code owner config
     * @return a {@link CodeOwnerConfigFile} for the code owner config with the specified key
     * @throws IOException if the repository can't be accessed for some reason
     * @throws ConfigInvalidException if the code owner config exists but can't be read due to an
     *     invalid format
     */
    public CodeOwnerConfigFile load(
        String defaultFileName,
        CodeOwnerConfigParser codeOwnerConfigParser,
        RevWalk revWalk,
        ObjectId revision,
        CodeOwnerConfig.Key codeOwnerConfigKey)
        throws IOException, ConfigInvalidException {
      requireNonNull(defaultFileName, "defaultFileName");
      requireNonNull(codeOwnerConfigParser, "codeOwnerConfigParser");
      requireNonNull(revWalk, "revWalk");
      requireNonNull(revision, "revision");
      requireNonNull(codeOwnerConfigKey, "codeOwnerConfigKey");

      CodeOwnerConfigFile codeOwnerConfigFile =
          new CodeOwnerConfigFile(
              codeOwnerMetrics, defaultFileName, codeOwnerConfigParser, codeOwnerConfigKey);
      codeOwnerConfigFile.load(codeOwnerConfigKey.project(), revWalk, revision);
      return codeOwnerConfigFile;
    }

    /**
     * Creates a {@link CodeOwnerConfigFile} for a code owner config from the current revision in
     * the branch.
     *
     * @param defaultFileName the name of the code owner configuration files that should be used if
     *     none is specified in the code owner config key
     * @param codeOwnerConfigParser the parser that should be used to parse code owner config files
     * @param repository the repository in which the code owner config is stored
     * @param codeOwnerConfigKey the key of the code owner config
     * @return a {@link CodeOwnerConfigFile} for the code owner config with the specified key
     * @throws IOException if the repository can't be accessed for some reason
     * @throws ConfigInvalidException if the code owner config exists but can't be read due to an
     *     invalid format
     * @see #load(String, CodeOwnerConfigParser, RevWalk, ObjectId, CodeOwnerConfig.Key)
     */
    public CodeOwnerConfigFile loadCurrent(
        String defaultFileName,
        CodeOwnerConfigParser codeOwnerConfigParser,
        Repository repository,
        CodeOwnerConfig.Key codeOwnerConfigKey)
        throws IOException, ConfigInvalidException {
      requireNonNull(defaultFileName, "defaultFileName");
      requireNonNull(codeOwnerConfigParser, "codeOwnerConfigParser");
      requireNonNull(repository, "repository");
      requireNonNull(codeOwnerConfigKey, "codeOwnerConfigKey");

      CodeOwnerConfigFile codeOwnerConfigFile =
          new CodeOwnerConfigFile(
              codeOwnerMetrics, defaultFileName, codeOwnerConfigParser, codeOwnerConfigKey);
      codeOwnerConfigFile.load(codeOwnerConfigKey.project(), repository);
      return codeOwnerConfigFile;
    }
  }

  private final CodeOwnerMetrics codeOwnerMetrics;
  private final String defaultFileName;
  private final CodeOwnerConfigParser codeOwnerConfigParser;
  private final CodeOwnerConfig.Key codeOwnerConfigKey;

  private boolean isLoaded = false;
  private Optional<CodeOwnerConfig> loadedCodeOwnersConfig = Optional.empty();
  private Optional<CodeOwnerConfigUpdate> codeOwnerConfigUpdate = Optional.empty();

  private CodeOwnerConfigFile(
      CodeOwnerMetrics codeOwnerMetrics,
      String defaultFileName,
      CodeOwnerConfigParser codeOwnerConfigParser,
      CodeOwnerConfig.Key codeOwnerConfigKey) {
    this.codeOwnerMetrics = codeOwnerMetrics;
    this.defaultFileName = defaultFileName;
    this.codeOwnerConfigParser = codeOwnerConfigParser;
    this.codeOwnerConfigKey = codeOwnerConfigKey;
  }

  /**
   * Returns the loaded code owner config if it exists.
   *
   * @return the loaded code owner config, or {@link Optional#empty()} if the code owner config
   *     doesn't exist
   */
  public Optional<CodeOwnerConfig> getLoadedCodeOwnerConfig() {
    checkLoaded();

    // If a loaded code owner config is present, update its revision if it is outdated.
    if (loadedCodeOwnersConfig.isPresent()
        && (!loadedCodeOwnersConfig.get().revision().equals(revision))) {
      loadedCodeOwnersConfig =
          Optional.of(loadedCodeOwnersConfig.get().toBuilder().setRevision(revision).build());
    }

    return loadedCodeOwnersConfig;
  }

  /**
   * Specifies how the current code owner config should be updated.
   *
   * <p>If the code owner config is newly created, the {@link CodeOwnerConfigUpdate} can be used to
   * specify optional properties.
   *
   * <p>If the update leads to an empty code owner config, the code owner config file is deleted.
   *
   * <p><strong>Note:</strong> This method doesn't perform the update. It only contains the
   * instructions for the update. To apply the update for real, call {@link
   * #commit(com.google.gerrit.server.git.meta.MetaDataUpdate)} on this {@link CodeOwnerConfigFile}.
   *
   * @param codeOwnerConfigUpdate an {@code CodeOwnerConfigUpdate} outlining the modifications which
   *     should be applied
   * @return this {@code CodeOwnerConfigFile} instance to allow chaining calls
   */
  public CodeOwnerConfigFile setCodeOwnerConfigUpdate(CodeOwnerConfigUpdate codeOwnerConfigUpdate) {
    this.codeOwnerConfigUpdate = Optional.of(codeOwnerConfigUpdate);
    return this;
  }

  @Override
  protected String getRefName() {
    return codeOwnerConfigKey.branchNameKey().branch();
  }

  @Override
  protected byte[] readFile(String fileName) throws IOException {
    try (Timer0.Context ctx = codeOwnerMetrics.readCodeOwnerConfig.start()) {
      return super.readFile(fileName);
    }
  }

  @Override
  protected void onLoad() throws IOException, ConfigInvalidException {
    if (revision != null) {
      String codeOwnerConfigFilePath =
          JgitPath.of(codeOwnerConfigKey.filePath(defaultFileName)).get();
      Optional<String> codeOwnerConfigFileContent = getFileIfItExists(codeOwnerConfigFilePath);
      if (codeOwnerConfigFileContent.isPresent()) {
        try (Timer1.Context<String> ctx =
            codeOwnerMetrics.parseCodeOwnerConfig.start(
                codeOwnerConfigParser.getClass().getSimpleName())) {
          loadedCodeOwnersConfig =
              Optional.of(
                  codeOwnerConfigParser.parse(
                      revision, codeOwnerConfigKey, codeOwnerConfigFileContent.get()));
        } catch (CodeOwnerConfigParseException e) {
          throw new InvalidCodeOwnerConfigException(
              e.getFullMessage(defaultFileName),
              projectName,
              getRefName(),
              codeOwnerConfigFilePath,
              e);
        }
      }
    }

    isLoaded = true;
  }

  /**
   * Loads the file with the given path and returns the file content if the file exists.
   *
   * @param filePath the path of the file that should be loaded
   * @return the content of the file if it exists, otherwise {@link Optional#empty()}.
   */
  private Optional<String> getFileIfItExists(String filePath) throws IOException {
    try (TreeWalk tw = TreeWalk.forPath(rw.getObjectReader(), filePath, revision.getTree())) {
      if (tw != null) {
        return Optional.of(readUTF8(filePath));
      }
    }
    return Optional.empty();
  }

  @Override
  public RevCommit commit(MetaDataUpdate update) throws IOException {
    // Reject the creation of a code owner config if the branch doesn't exist.
    checkState(
        update.getRepository().exactRef(getRefName()) != null,
        "branch %s does not exist",
        getRefName());
    // The commit goes to an ordinary branch (e.g. refs/heads/main). PLUGIN context is enough for
    // such cases.
    try(RefUpdateContext ctx = RefUpdateContext.open(PLUGIN)) {
      return super.commit(update);
    }
  }

  @Override
  protected boolean onSave(CommitBuilder commit) throws IOException, ConfigInvalidException {
    checkLoaded();

    if (!codeOwnerConfigUpdate.isPresent()) {
      // Code owner config was neither created nor changed. -> A new commit isn't necessary.
      return false;
    }

    // Update the code owner config.
    CodeOwnerConfig originalCodeOwnerConfig =
        loadedCodeOwnersConfig.orElse(
            CodeOwnerConfig.builder(codeOwnerConfigKey, revision).build());
    CodeOwnerConfig updatedCodeOwnerConfig =
        updateCodeOwnerConfig(originalCodeOwnerConfig, codeOwnerConfigUpdate.get());

    // Do not create a new commit if the code owner config didn't change.
    if (updatedCodeOwnerConfig.equals(originalCodeOwnerConfig)) {
      return false;
    }

    // Compute the new content of the code owner config file.
    String codeOwnerConfigFileContent =
        codeOwnerConfigParser.formatAsString(updatedCodeOwnerConfig);

    // Save the new code owner config.
    saveUTF8(
        JgitPath.of(codeOwnerConfigKey.filePath(defaultFileName)).get(),
        codeOwnerConfigFileContent);

    // If the file content is empty, the update led to a deletion of the code owner config file.
    boolean isDeleted = codeOwnerConfigFileContent.isEmpty();

    // Set a commit message if none was set yet.
    if (Strings.isNullOrEmpty(commit.getMessage())) {
      commit.setMessage(
          String.format(
              "%s code owner config",
              loadedCodeOwnersConfig.isPresent() ? (isDeleted ? "Delete" : "Update") : "Create"));
    }

    loadedCodeOwnersConfig = isDeleted ? Optional.empty() : Optional.of(updatedCodeOwnerConfig);
    codeOwnerConfigUpdate = Optional.empty();

    return true;
  }

  private static CodeOwnerConfig updateCodeOwnerConfig(
      CodeOwnerConfig codeOwnerConfig, CodeOwnerConfigUpdate codeOwnerConfigUpdate) {
    CodeOwnerConfig.Builder codeOwnerConfigBuilder = codeOwnerConfig.toBuilder();
    codeOwnerConfigUpdate
        .ignoreParentCodeOwners()
        .ifPresent(codeOwnerConfigBuilder::setIgnoreParentCodeOwners);
    codeOwnerConfigBuilder.setCodeOwnerSets(
        codeOwnerConfigUpdate
            .codeOwnerSetsModification()
            .apply(codeOwnerConfig.codeOwnerSetsAsList()));
    codeOwnerConfigBuilder.setImports(
        codeOwnerConfigUpdate.importsModification().apply(codeOwnerConfig.importsAsList()));
    return codeOwnerConfigBuilder.build();
  }

  private void checkLoaded() {
    checkState(isLoaded, "Code owner config %s not loaded yet", codeOwnerConfigKey);
  }
}
