// 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.google.gerrit.server.restapi.project;

import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.gerrit.entities.RefNames.isConfigRef;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.BRANCH_MODIFICATION;
import static java.lang.String.format;
import static org.eclipse.jgit.lib.Constants.R_REFS;
import static org.eclipse.jgit.lib.Constants.R_TAGS;
import static org.eclipse.jgit.transport.ReceiveCommand.Type.DELETE;

import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.git.LockFailureException;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.RefPermission;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.project.RefValidationHelper;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.ReceiveCommand.Result;

@Singleton
public class DeleteRef {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final Provider<IdentifiedUser> identifiedUser;
  private final PermissionBackend permissionBackend;
  private final GitRepositoryManager repoManager;
  private final GitReferenceUpdated referenceUpdated;
  private final RefValidationHelper refDeletionValidator;
  private final Provider<InternalChangeQuery> queryProvider;

  @Inject
  DeleteRef(
      Provider<IdentifiedUser> identifiedUser,
      PermissionBackend permissionBackend,
      GitRepositoryManager repoManager,
      GitReferenceUpdated referenceUpdated,
      RefValidationHelper.Factory refDeletionValidatorFactory,
      Provider<InternalChangeQuery> queryProvider) {
    this.identifiedUser = identifiedUser;
    this.permissionBackend = permissionBackend;
    this.repoManager = repoManager;
    this.referenceUpdated = referenceUpdated;
    this.refDeletionValidator = refDeletionValidatorFactory.create(DELETE);
    this.queryProvider = queryProvider;
  }

  /**
   * Deletes a single ref from the repository.
   *
   * @param projectState the {@code ProjectState} of the project containing the target ref.
   * @param ref the ref to be deleted.
   */
  public void deleteSingleRef(ProjectState projectState, String ref)
      throws IOException, ResourceConflictException, AuthException, PermissionBackendException {
    deleteSingleRef(projectState, ref, null);
  }

  /**
   * Deletes a single ref from the repository.
   *
   * @param projectState the {@code ProjectState} of the project containing the target ref.
   * @param ref the ref to be deleted.
   * @param prefix the prefix of the ref.
   */
  public void deleteSingleRef(ProjectState projectState, String ref, @Nullable String prefix)
      throws IOException, ResourceConflictException, AuthException, PermissionBackendException {
    try (RefUpdateContext ctx = RefUpdateContext.open(BRANCH_MODIFICATION)) {
      if (prefix != null && !ref.startsWith(R_REFS)) {
        ref = prefix + ref;
      }

      projectState.checkStatePermitsWrite();
      permissionBackend
          .currentUser()
          .project(projectState.getNameKey())
          .ref(ref)
          .check(RefPermission.DELETE);

      try (Repository repository = repoManager.openRepository(projectState.getNameKey())) {
        Ref refObj = repository.exactRef(ref);
        if (refObj == null) {
          throw new ResourceConflictException(String.format("ref %s doesn't exist", ref));
        }
        RefUpdate u = repository.updateRef(ref);
        u.setExpectedOldObjectId(refObj.getObjectId());
        u.setNewObjectId(ObjectId.zeroId());
        u.setForceUpdate(true);
        refDeletionValidator.validateRefOperation(
            projectState.getName(),
            identifiedUser.get(),
            u,
            /* pushOptions */ ImmutableListMultimap.of());
        RefUpdate.Result result = u.delete();

        switch (result) {
          case NEW:
          case NO_CHANGE:
          case FAST_FORWARD:
          case FORCED:
            referenceUpdated.fire(
                projectState.getNameKey(),
                u,
                ReceiveCommand.Type.DELETE,
                identifiedUser.get().state());
            break;

          case REJECTED_CURRENT_BRANCH:
            logger.atFine().log("Cannot delete current branch %s: %s", ref, result.name());
            throw new ResourceConflictException("cannot delete current branch");

          case LOCK_FAILURE:
            throw new LockFailureException(String.format("Cannot delete %s", ref), u);
          case IO_FAILURE:
          case NOT_ATTEMPTED:
          case REJECTED:
          case RENAMED:
          case REJECTED_MISSING_OBJECT:
          case REJECTED_OTHER_REASON:
          default:
            throw new StorageException(String.format("Cannot delete %s: %s", ref, result.name()));
        }
      }
    }
  }

  /**
   * Deletes a set of refs from the repository.
   *
   * @param projectState the {@code ProjectState} of the project whose refs are to be deleted.
   * @param refsToDelete the refs to be deleted.
   * @param prefix the prefix to add to abbreviated refs, eg. "refs/heads/".
   */
  public void deleteMultipleRefs(
      ProjectState projectState, ImmutableSet<String> refsToDelete, String prefix)
      throws IOException, ResourceConflictException, PermissionBackendException, AuthException {
    if (refsToDelete.isEmpty()) {
      return;
    }

    if (refsToDelete.size() == 1) {
      deleteSingleRef(projectState, Iterables.getOnlyElement(refsToDelete), prefix);
      return;
    }

    try (Repository repository = repoManager.openRepository(projectState.getNameKey())) {
      BatchRefUpdate batchUpdate = repository.getRefDatabase().newBatchUpdate();
      batchUpdate.setAtomic(false);
      ImmutableSet<String> refs =
          prefix == null
              ? refsToDelete
              : refsToDelete.stream()
                  .map(ref -> ref.startsWith(R_REFS) ? ref : prefix + ref)
                  .collect(toImmutableSet());
      for (String ref : refs) {
        batchUpdate.addCommand(createDeleteCommand(projectState, repository, ref));
      }
      try (RevWalk rw = new RevWalk(repository)) {
        batchUpdate.execute(rw, NullProgressMonitor.INSTANCE);
      }
      StringBuilder errorMessages = new StringBuilder();
      for (ReceiveCommand command : batchUpdate.getCommands()) {
        if (command.getResult() == Result.OK) {
          postDeletion(projectState.getNameKey(), command);
        } else {
          appendAndLogErrorMessage(errorMessages, command);
        }
      }
      if (errorMessages.length() > 0) {
        throw new ResourceConflictException(errorMessages.toString());
      }
    }
  }

  private ReceiveCommand createDeleteCommand(
      ProjectState projectState, Repository r, String refName)
      throws IOException, ResourceConflictException, PermissionBackendException {
    Ref ref = r.getRefDatabase().exactRef(refName);
    ReceiveCommand command;
    if (ref == null) {
      command = new ReceiveCommand(ObjectId.zeroId(), ObjectId.zeroId(), refName);
      command.setResult(
          Result.REJECTED_OTHER_REASON,
          "it doesn't exist or you do not have permission to delete it");
      return command;
    }
    command = new ReceiveCommand(ref.getObjectId(), ObjectId.zeroId(), ref.getName());

    if (isConfigRef(refName)) {
      // Never allow to delete the meta config branch.
      command.setResult(Result.REJECTED_OTHER_REASON, "not allowed to delete branch " + refName);
    } else if (!permissionBackend
        .currentUser()
        .project(projectState.getNameKey())
        .ref(refName)
        .test(RefPermission.DELETE)) {
      command.setResult(
          Result.REJECTED_OTHER_REASON,
          "it doesn't exist or you do not have permission to delete it");
    }

    if (!projectState.statePermitsWrite()) {
      command.setResult(Result.REJECTED_OTHER_REASON, "project state does not permit write");
    }

    if (!refName.startsWith(R_TAGS)) {
      BranchNameKey branchKey = BranchNameKey.create(projectState.getNameKey(), ref.getName());
      if (!queryProvider.get().setLimit(1).byBranchOpen(branchKey).isEmpty()) {
        command.setResult(Result.REJECTED_OTHER_REASON, "it has open changes");
      }
    }

    RefUpdate u = r.updateRef(refName);
    u.setForceUpdate(true);
    u.setExpectedOldObjectId(ref.getObjectId());
    u.setNewObjectId(ObjectId.zeroId());
    refDeletionValidator.validateRefOperation(
        projectState.getName(),
        identifiedUser.get(),
        u,
        /* pushOptions */ ImmutableListMultimap.of());
    return command;
  }

  private void appendAndLogErrorMessage(StringBuilder errorMessages, ReceiveCommand cmd) {
    String msg;
    switch (cmd.getResult()) {
      case REJECTED_CURRENT_BRANCH:
        msg = format("Cannot delete %s: it is the current branch", cmd.getRefName());
        break;
      case REJECTED_OTHER_REASON:
        msg = format("Cannot delete %s: %s", cmd.getRefName(), cmd.getMessage());
        break;
      case LOCK_FAILURE:
      case NOT_ATTEMPTED:
      case OK:
      case REJECTED_MISSING_OBJECT:
      case REJECTED_NOCREATE:
      case REJECTED_NODELETE:
      case REJECTED_NONFASTFORWARD:
      default:
        msg = format("Cannot delete %s: %s", cmd.getRefName(), cmd.getResult());
        break;
    }
    logger.atSevere().log("%s", msg);
    errorMessages.append(msg);
    errorMessages.append("\n");
  }

  private void postDeletion(Project.NameKey project, ReceiveCommand cmd) {
    referenceUpdated.fire(project, cmd, identifiedUser.get().state());
  }
}
