// 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.project;

import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
import static org.eclipse.jgit.lib.Constants.R_TAGS;
import static org.eclipse.jgit.transport.ReceiveCommand.Type.DELETE;

import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Branch;
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.query.change.InternalChangeQuery;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jgit.errors.LockFailedException;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DeleteRef {
  private static final Logger log = LoggerFactory.getLogger(DeleteRef.class);

  private static final int MAX_LOCK_FAILURE_CALLS = 10;
  private static final long SLEEP_ON_LOCK_FAILURE_MS = 15;

  private final Provider<IdentifiedUser> identifiedUser;
  private final GitRepositoryManager repoManager;
  private final GitReferenceUpdated referenceUpdated;
  private final RefValidationHelper refDeletionValidator;
  private final Provider<InternalChangeQuery> queryProvider;
  private final ProjectResource resource;
  private final List<String> refsToDelete;
  private String prefix;

  public interface Factory {
    DeleteRef create(ProjectResource r);
  }

  @AssistedInject
  DeleteRef(
      Provider<IdentifiedUser> identifiedUser,
      GitRepositoryManager repoManager,
      GitReferenceUpdated referenceUpdated,
      RefValidationHelper.Factory refDeletionValidatorFactory,
      Provider<InternalChangeQuery> queryProvider,
      @Assisted ProjectResource resource) {
    this.identifiedUser = identifiedUser;
    this.repoManager = repoManager;
    this.referenceUpdated = referenceUpdated;
    this.refDeletionValidator = refDeletionValidatorFactory.create(DELETE);
    this.queryProvider = queryProvider;
    this.resource = resource;
    this.refsToDelete = new ArrayList<>();
  }

  public DeleteRef ref(String ref) {
    this.refsToDelete.add(ref);
    return this;
  }

  public DeleteRef refs(List<String> refs) {
    this.refsToDelete.addAll(refs);
    return this;
  }

  public DeleteRef prefix(String prefix) {
    this.prefix = prefix;
    return this;
  }

  public void delete() throws OrmException, IOException, ResourceConflictException, AuthException {
    if (!refsToDelete.isEmpty()) {
      try (Repository r = repoManager.openRepository(resource.getNameKey())) {
        if (refsToDelete.size() == 1) {
          deleteSingleRef(r);
        } else {
          deleteMultipleRefs(r);
        }
      }
    }
  }

  private void deleteSingleRef(Repository r)
      throws IOException, ResourceConflictException, AuthException {
    String ref = refsToDelete.get(0);
    if (prefix != null && !ref.startsWith(prefix)) {
      ref = prefix + ref;
    }

    if (!resource.getControl().controlForRef(ref).canDelete()) {
      throw new AuthException("delete not permitted for " + ref);
    }

    RefUpdate.Result result;
    RefUpdate u = r.updateRef(ref);
    u.setExpectedOldObjectId(r.exactRef(ref).getObjectId());
    u.setNewObjectId(ObjectId.zeroId());
    u.setForceUpdate(true);
    refDeletionValidator.validateRefOperation(resource.getName(), identifiedUser.get(), u);
    int remainingLockFailureCalls = MAX_LOCK_FAILURE_CALLS;
    for (; ; ) {
      try {
        result = u.delete();
      } catch (LockFailedException e) {
        result = RefUpdate.Result.LOCK_FAILURE;
      } catch (IOException e) {
        log.error("Cannot delete " + ref, e);
        throw e;
      }
      if (result == RefUpdate.Result.LOCK_FAILURE && --remainingLockFailureCalls > 0) {
        try {
          Thread.sleep(SLEEP_ON_LOCK_FAILURE_MS);
        } catch (InterruptedException ie) {
          // ignore
        }
      } else {
        break;
      }
    }

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

      case REJECTED_CURRENT_BRANCH:
        log.error("Cannot delete " + ref + ": " + result.name());
        throw new ResourceConflictException("cannot delete current branch");

      case IO_FAILURE:
      case LOCK_FAILURE:
      case NOT_ATTEMPTED:
      case REJECTED:
      case RENAMED:
      default:
        log.error("Cannot delete " + ref + ": " + result.name());
        throw new ResourceConflictException("cannot delete: " + result.name());
    }
  }

  private void deleteMultipleRefs(Repository r)
      throws OrmException, IOException, ResourceConflictException {
    BatchRefUpdate batchUpdate = r.getRefDatabase().newBatchUpdate();
    List<String> refs =
        prefix == null
            ? refsToDelete
            : refsToDelete.stream()
                .map(ref -> ref.startsWith(prefix) ? ref : prefix + ref)
                .collect(toList());
    for (String ref : refs) {
      batchUpdate.addCommand(createDeleteCommand(resource, r, ref));
    }
    try (RevWalk rw = new RevWalk(r)) {
      batchUpdate.execute(rw, NullProgressMonitor.INSTANCE);
    }
    StringBuilder errorMessages = new StringBuilder();
    for (ReceiveCommand command : batchUpdate.getCommands()) {
      if (command.getResult() == Result.OK) {
        postDeletion(resource, command);
      } else {
        appendAndLogErrorMessage(errorMessages, command);
      }
    }
    if (errorMessages.length() > 0) {
      throw new ResourceConflictException(errorMessages.toString());
    }
  }

  private ReceiveCommand createDeleteCommand(ProjectResource project, Repository r, String refName)
      throws OrmException, IOException, ResourceConflictException {
    Ref ref = r.getRefDatabase().getRef(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 (!project.getControl().controlForRef(refName).canDelete()) {
      command.setResult(
          Result.REJECTED_OTHER_REASON,
          "it doesn't exist or you do not have permission to delete it");
    }

    if (!refName.startsWith(R_TAGS)) {
      Branch.NameKey branchKey = new Branch.NameKey(project.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(project.getName(), identifiedUser.get(), u);
    return command;
  }

  private void appendAndLogErrorMessage(StringBuilder errorMessages, ReceiveCommand cmd) {
    String msg = null;
    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;
    }
    log.error(msg);
    errorMessages.append(msg);
    errorMessages.append("\n");
  }

  private void postDeletion(ProjectResource project, ReceiveCommand cmd) {
    referenceUpdated.fire(project.getNameKey(), cmd, identifiedUser.get().getAccount());
  }
}
