// 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 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.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.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.
   * @throws IOException
   * @throws ResourceConflictException
   */
  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.
   * @throws IOException
   * @throws ResourceConflictException
   */
  public void deleteSingleRef(ProjectState projectState, String ref, @Nullable String prefix)
      throws IOException, ResourceConflictException, AuthException, PermissionBackendException {
    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())) {
      RefUpdate.Result result;
      RefUpdate u = repository.updateRef(ref);
      u.setExpectedOldObjectId(repository.exactRef(ref).getObjectId());
      u.setNewObjectId(ObjectId.zeroId());
      u.setForceUpdate(true);
      refDeletionValidator.validateRefOperation(projectState.getName(), identifiedUser.get(), u);
      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/".
   * @throws IOException
   * @throws ResourceConflictException
   * @throws PermissionBackendException
   */
  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 {
      try {
        permissionBackend
            .currentUser()
            .project(projectState.getNameKey())
            .ref(refName)
            .check(RefPermission.DELETE);
      } catch (AuthException denied) {
        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(r.exactRef(refName).getObjectId());
    u.setNewObjectId(ObjectId.zeroId());
    refDeletionValidator.validateRefOperation(projectState.getName(), identifiedUser.get(), u);
    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(msg);
    errorMessages.append(msg);
    errorMessages.append("\n");
  }

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