// 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 java.util.Objects.requireNonNull;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
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 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 #load(String,
 * CodeOwnerConfigParser, RevWalk, ObjectId, CodeOwnerConfig.Key)} and {@link #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 {
  /**
   * 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 static 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(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 static 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(defaultFileName, codeOwnerConfigParser, codeOwnerConfigKey);
    codeOwnerConfigFile.load(codeOwnerConfigKey.project(), repository);
    return codeOwnerConfigFile;
  }

  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(
      String defaultFileName,
      CodeOwnerConfigParser codeOwnerConfigParser,
      CodeOwnerConfig.Key codeOwnerConfigKey) {
    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 void onLoad() throws IOException, ConfigInvalidException {
    if (revision != null) {
      Optional<String> codeOwnerConfigFileContent =
          getFileIfItExists(JgitPath.of(codeOwnerConfigKey.filePath(defaultFileName)).get());
      if (codeOwnerConfigFileContent.isPresent()) {
        try {
          loadedCodeOwnersConfig =
              Optional.of(
                  codeOwnerConfigParser.parse(
                      revision, codeOwnerConfigKey, codeOwnerConfigFileContent.get()));
        } catch (CodeOwnerConfigParseException e) {
          throw new ConfigInvalidException(e.getFullMessage(defaultFileName), 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());

    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);
  }
}
