// 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.google.gerrit.plugins.checks.db;

import com.google.common.base.Throwables;
import com.google.gerrit.exceptions.DuplicateKeyException;
import com.google.gerrit.git.LockFailureException;
import com.google.gerrit.git.RefUpdateUtil;
import com.google.gerrit.plugins.checks.Checker;
import com.google.gerrit.plugins.checks.CheckerCreation;
import com.google.gerrit.plugins.checks.CheckerUpdate;
import com.google.gerrit.plugins.checks.CheckerUuid;
import com.google.gerrit.plugins.checks.CheckersUpdate;
import com.google.gerrit.plugins.checks.NoSuchCheckerException;
import com.google.gerrit.plugins.checks.api.CheckerStatus;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gerrit.server.update.RetryHelper.ActionType;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;

/** Class to write checkers to NoteDb. */
class NoteDbCheckersUpdate implements CheckersUpdate {
  interface Factory {
    /**
     * Creates a {@code CheckersUpdate} which uses the identity of the specified user to mark
     * database modifications executed by it. For NoteDb, this identity is used as author and
     * committer for all related commits.
     *
     * <p><strong>Note</strong>: Please use this method with care and consider using the {@link
     * com.google.gerrit.server.UserInitiated} annotation on the provider of a {@code
     * CheckersUpdate} instead.
     *
     * @param currentUser the user to which modifications should be attributed
     */
    NoteDbCheckersUpdate create(IdentifiedUser currentUser);

    /**
     * Creates a {@code CheckersUpdate} which uses the server identity to mark database
     * modifications executed by it. For NoteDb, this identity is used as author and committer for
     * all related commits.
     *
     * <p><strong>Note</strong>: Please use this method with care and consider using the {@link
     * com.google.gerrit.server.ServerInitiated} annotation on the provider of a {@code
     * CheckersUpdate} instead.
     */
    NoteDbCheckersUpdate createWithServerIdent();
  }

  private final GitRepositoryManager repoManager;
  private final AllProjectsName allProjectsName;
  private final MetaDataUpdateFactory metaDataUpdateFactory;
  private final GitReferenceUpdated gitRefUpdated;
  private final RetryHelper retryHelper;
  private final Optional<IdentifiedUser> currentUser;

  @AssistedInject
  NoteDbCheckersUpdate(
      GitRepositoryManager repoManager,
      AllProjectsName allProjectsName,
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      GitReferenceUpdated gitRefUpdated,
      RetryHelper retryHelper,
      @GerritPersonIdent PersonIdent serverIdent) {
    this(
        repoManager,
        allProjectsName,
        metaDataUpdateInternalFactory,
        gitRefUpdated,
        retryHelper,
        serverIdent,
        Optional.empty());
  }

  @AssistedInject
  NoteDbCheckersUpdate(
      GitRepositoryManager repoManager,
      AllProjectsName allProjectsName,
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      GitReferenceUpdated gitRefUpdated,
      RetryHelper retryHelper,
      @GerritPersonIdent PersonIdent serverIdent,
      @Assisted IdentifiedUser currentUser) {
    this(
        repoManager,
        allProjectsName,
        metaDataUpdateInternalFactory,
        gitRefUpdated,
        retryHelper,
        serverIdent,
        Optional.of(currentUser));
  }

  private NoteDbCheckersUpdate(
      GitRepositoryManager repoManager,
      AllProjectsName allProjectsName,
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      GitReferenceUpdated gitRefUpdated,
      RetryHelper retryHelper,
      @GerritPersonIdent PersonIdent serverIdent,
      Optional<IdentifiedUser> currentUser) {
    this.repoManager = repoManager;
    this.allProjectsName = allProjectsName;
    this.gitRefUpdated = gitRefUpdated;
    this.retryHelper = retryHelper;
    this.currentUser = currentUser;

    metaDataUpdateFactory =
        getMetaDataUpdateFactory(metaDataUpdateInternalFactory, currentUser, serverIdent);
  }

  @Override
  public Checker createChecker(CheckerCreation checkerCreation, CheckerUpdate checkerUpdate)
      throws DuplicateKeyException, IOException, ConfigInvalidException {
    try {
      return retryHelper.execute(
          RetryHelper.ActionType.PLUGIN_UPDATE,
          () -> createCheckerInNoteDb(checkerCreation, checkerUpdate),
          LockFailureException.class::isInstance);
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      Throwables.throwIfInstanceOf(e, DuplicateKeyException.class);
      Throwables.throwIfInstanceOf(e, IOException.class);
      Throwables.throwIfInstanceOf(e, ConfigInvalidException.class);
      throw new IOException(e);
    }
  }

  private Checker createCheckerInNoteDb(
      CheckerCreation checkerCreation, CheckerUpdate checkerUpdate)
      throws DuplicateKeyException, IOException, ConfigInvalidException {
    try (Repository allProjectsRepo = repoManager.openRepository(allProjectsName)) {
      CheckerConfig checkerConfig =
          CheckerConfig.createForNewChecker(allProjectsName, allProjectsRepo, checkerCreation);
      checkerConfig.setCheckerUpdate(checkerUpdate);

      CheckersByRepositoryNotes checkersByRepositoryNotes =
          CheckersByRepositoryNotes.load(allProjectsName, allProjectsRepo);
      if (!checkerUpdate.getStatus().isPresent()
          || checkerUpdate.getStatus().get() == CheckerStatus.ENABLED) {
        // Only inserts to the notes if the status is not set or set as "ENABLED". Does not insert
        // if the checker is DISABLED.
        checkersByRepositoryNotes.insert(
            checkerCreation.getCheckerUuid(), checkerCreation.getRepository());
      }

      commit(allProjectsRepo, checkerConfig, checkersByRepositoryNotes);

      return checkerConfig
          .getLoadedChecker()
          .orElseThrow(
              () -> new IllegalStateException("Created checker wasn't automatically loaded"));
    }
  }

  private void commit(
      Repository allProjectsRepo,
      CheckerConfig checkerConfig,
      CheckersByRepositoryNotes checkersByRepositoryNotes)
      throws IOException {
    BatchRefUpdate batchRefUpdate = allProjectsRepo.getRefDatabase().newBatchUpdate();
    try (MetaDataUpdate metaDataUpdate =
        metaDataUpdateFactory.create(allProjectsName, allProjectsRepo, batchRefUpdate)) {
      checkerConfig.commit(metaDataUpdate);
      checkersByRepositoryNotes.commit(metaDataUpdate);
    }
    RefUpdateUtil.executeChecked(batchRefUpdate, allProjectsRepo);

    gitRefUpdated.fire(
        allProjectsName, batchRefUpdate, currentUser.map(user -> user.state()).orElse(null));
  }

  private static MetaDataUpdateFactory getMetaDataUpdateFactory(
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      Optional<IdentifiedUser> currentUser,
      PersonIdent serverIdent) {
    return (projectName, repository, batchRefUpdate) -> {
      MetaDataUpdate metaDataUpdate =
          metaDataUpdateInternalFactory.create(projectName, repository, batchRefUpdate);
      metaDataUpdate.getCommitBuilder().setCommitter(serverIdent);
      PersonIdent authorIdent;
      if (currentUser.isPresent()) {
        metaDataUpdate.setAuthor(currentUser.get());
        authorIdent =
            currentUser.get().newCommitterIdent(serverIdent.getWhen(), serverIdent.getTimeZone());
      } else {
        authorIdent = serverIdent;
      }
      metaDataUpdate.getCommitBuilder().setAuthor(authorIdent);
      return metaDataUpdate;
    };
  }

  @FunctionalInterface
  private interface MetaDataUpdateFactory {
    MetaDataUpdate create(
        Project.NameKey projectName, Repository repository, BatchRefUpdate batchRefUpdate)
        throws IOException;
  }

  @Override
  public Checker updateChecker(CheckerUuid checkerUuid, CheckerUpdate checkerUpdate)
      throws NoSuchCheckerException, IOException, ConfigInvalidException {
    return updateCheckerWithRetry(checkerUuid, checkerUpdate);
  }

  private Checker updateCheckerWithRetry(CheckerUuid checkerUuid, CheckerUpdate checkerUpdate)
      throws NoSuchCheckerException, IOException, ConfigInvalidException {
    try {
      return retryHelper.execute(
          ActionType.PLUGIN_UPDATE,
          () -> updateCheckerInNoteDb(checkerUuid, checkerUpdate),
          LockFailureException.class::isInstance);
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      Throwables.throwIfInstanceOf(e, IOException.class);
      Throwables.throwIfInstanceOf(e, ConfigInvalidException.class);
      Throwables.throwIfInstanceOf(e, NoSuchCheckerException.class);
      throw new IOException(e);
    }
  }

  private Checker updateCheckerInNoteDb(CheckerUuid checkerUuid, CheckerUpdate checkerUpdate)
      throws IOException, ConfigInvalidException, NoSuchCheckerException {
    try (Repository allProjectsRepo = repoManager.openRepository(allProjectsName)) {
      CheckerConfig checkerConfig =
          CheckerConfig.loadForChecker(allProjectsName, allProjectsRepo, checkerUuid);
      checkerConfig.setCheckerUpdate(checkerUpdate);
      if (!checkerConfig.getLoadedChecker().isPresent()) {
        throw new NoSuchCheckerException(checkerUuid);
      }

      CheckersByRepositoryNotes checkersByRepositoryNotes =
          CheckersByRepositoryNotes.load(allProjectsName, allProjectsRepo);

      Checker checker = checkerConfig.getLoadedChecker().get();
      Project.NameKey oldRepositoryName = checker.getRepository();
      Project.NameKey newRepositoryName = checkerUpdate.getRepository().orElse(oldRepositoryName);

      CheckerStatus newStatus = checkerUpdate.getStatus().orElse(checker.getStatus());
      switch (newStatus) {
          // May produce some redundant notes updates, but CheckersByRepositoryNotes knows how to
          // short-circuit on no-ops, and the logic in this method is simple.
        case DISABLED:
          checkersByRepositoryNotes.remove(checkerUuid, oldRepositoryName);
          checkersByRepositoryNotes.remove(checkerUuid, newRepositoryName);
          break;
        case ENABLED:
          if (oldRepositoryName.equals(newRepositoryName)) {
            checkersByRepositoryNotes.insert(checkerUuid, newRepositoryName);
          } else {
            checkersByRepositoryNotes.update(checkerUuid, oldRepositoryName, newRepositoryName);
          }
          break;
        default:
          throw new IllegalStateException("invalid checker status: " + newStatus);
      }

      commit(allProjectsRepo, checkerConfig, checkersByRepositoryNotes);

      Checker updatedChecker =
          checkerConfig
              .getLoadedChecker()
              .orElseThrow(
                  () -> new IllegalStateException("Updated checker wasn't automatically loaded"));
      return updatedChecker;
    }
  }
}
