// Copyright (C) 2015 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.change;

import static com.google.gerrit.extensions.conditions.BooleanCondition.and;
import static com.google.gerrit.server.permissions.ChangePermission.ABANDON;
import static com.google.gerrit.server.permissions.RefPermission.CREATE_CHANGE;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static com.google.gerrit.server.query.change.ChangeData.asChanges;

import com.google.common.base.Strings;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.MoveInput;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

@Singleton
public class Move implements RestModifyView<ChangeResource, MoveInput>, UiAction<ChangeResource> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final PermissionBackend permissionBackend;
  private final BatchUpdate.Factory updateFactory;
  private final ChangeJson.Factory json;
  private final GitRepositoryManager repoManager;
  private final Provider<InternalChangeQuery> queryProvider;
  private final ChangeMessagesUtil cmUtil;
  private final PatchSetUtil psUtil;
  private final ApprovalsUtil approvalsUtil;
  private final ProjectCache projectCache;
  private final boolean moveEnabled;

  @Inject
  Move(
      PermissionBackend permissionBackend,
      BatchUpdate.Factory updateFactory,
      ChangeJson.Factory json,
      GitRepositoryManager repoManager,
      Provider<InternalChangeQuery> queryProvider,
      ChangeMessagesUtil cmUtil,
      PatchSetUtil psUtil,
      ApprovalsUtil approvalsUtil,
      ProjectCache projectCache,
      @GerritServerConfig Config gerritConfig) {
    this.permissionBackend = permissionBackend;
    this.updateFactory = updateFactory;
    this.json = json;
    this.repoManager = repoManager;
    this.queryProvider = queryProvider;
    this.cmUtil = cmUtil;
    this.psUtil = psUtil;
    this.approvalsUtil = approvalsUtil;
    this.projectCache = projectCache;
    this.moveEnabled = gerritConfig.getBoolean("change", null, "move", true);
  }

  @Override
  public Response<ChangeInfo> apply(ChangeResource rsrc, MoveInput input)
      throws RestApiException, UpdateException, PermissionBackendException, IOException {
    if (!moveEnabled) {
      // This will be removed with the above config once we reach consensus for the move change
      // behavior. See: https://bugs.chromium.org/p/gerrit/issues/detail?id=9877
      throw new MethodNotAllowedException("move changes endpoint is disabled");
    }

    Change change = rsrc.getChange();
    Project.NameKey project = rsrc.getProject();
    IdentifiedUser caller = rsrc.getUser().asIdentifiedUser();
    if (input.destinationBranch == null) {
      throw new BadRequestException("destination branch is required");
    }
    input.destinationBranch = RefNames.fullName(input.destinationBranch);

    if (!change.isNew()) {
      throw new ResourceConflictException("Change is " + ChangeUtil.status(change));
    }

    BranchNameKey newDest = BranchNameKey.create(project, input.destinationBranch);
    if (change.getDest().equals(newDest)) {
      throw new ResourceConflictException("Change is already destined for the specified branch");
    }

    // Not allowed to move if the current patch set is locked.
    psUtil.checkPatchSetNotLocked(rsrc.getNotes());

    // Keeping all votes can be confusing in the context of the destination branch, see the
    // discussion in
    // https://gerrit-review.googlesource.com/c/gerrit/+/129171
    // Only administrators are allowed to keep all labels at their own risk.
    try {
      if (input.keepAllVotes) {
        permissionBackend.user(caller).check(GlobalPermission.ADMINISTRATE_SERVER);
      }
    } catch (AuthException denied) {
      throw new AuthException("move is not permitted with keepAllVotes option", denied);
    }

    // Move requires abandoning this change, and creating a new change.
    try {
      rsrc.permissions().check(ABANDON);
      permissionBackend.user(caller).ref(newDest).check(CREATE_CHANGE);
    } catch (AuthException denied) {
      throw new AuthException("move not permitted", denied);
    }
    projectCache.get(project).orElseThrow(illegalState(project)).checkStatePermitsWrite();

    Op op = new Op(input);
    try (BatchUpdate u = updateFactory.create(project, caller, TimeUtil.nowTs())) {
      u.addOp(change.getId(), op);
      u.execute();
    }
    return Response.ok(json.noOptions().format(op.getChange()));
  }

  private class Op implements BatchUpdateOp {
    private final MoveInput input;

    private Change change;
    private BranchNameKey newDestKey;

    Op(MoveInput input) {
      this.input = input;
    }

    @Nullable
    public Change getChange() {
      return change;
    }

    @Override
    public boolean updateChange(ChangeContext ctx) throws ResourceConflictException, IOException {
      change = ctx.getChange();
      if (!change.isNew()) {
        throw new ResourceConflictException("Change is " + ChangeUtil.status(change));
      }

      Project.NameKey projectKey = change.getProject();
      newDestKey = BranchNameKey.create(projectKey, input.destinationBranch);
      BranchNameKey changePrevDest = change.getDest();
      if (changePrevDest.equals(newDestKey)) {
        throw new ResourceConflictException("Change is already destined for the specified branch");
      }

      final PatchSet.Id patchSetId = change.currentPatchSetId();
      try (Repository repo = repoManager.openRepository(projectKey);
          RevWalk revWalk = new RevWalk(repo)) {
        RevCommit currPatchsetRevCommit =
            revWalk.parseCommit(psUtil.current(ctx.getNotes()).commitId());
        if (currPatchsetRevCommit.getParentCount() > 1) {
          throw new ResourceConflictException("Merge commit cannot be moved");
        }

        ObjectId refId = repo.resolve(input.destinationBranch);
        // Check if destination ref exists in project repo
        if (refId == null) {
          throw new ResourceConflictException(
              "Destination " + input.destinationBranch + " not found in the project");
        }
        RevCommit refCommit = revWalk.parseCommit(refId);
        if (revWalk.isMergedInto(currPatchsetRevCommit, refCommit)) {
          throw new ResourceConflictException(
              "Current patchset revision is reachable from tip of " + input.destinationBranch);
        }
      }

      Change.Key changeKey = change.getKey();
      if (!asChanges(queryProvider.get().byBranchKey(newDestKey, changeKey)).isEmpty()) {
        throw new ResourceConflictException(
            "Destination "
                + newDestKey.shortName()
                + " has a different change with same change key "
                + changeKey);
      }

      if (!change.currentPatchSetId().equals(patchSetId)) {
        throw new ResourceConflictException("Patch set is not current");
      }

      PatchSet.Id psId = change.currentPatchSetId();
      ChangeUpdate update = ctx.getUpdate(psId);
      update.setBranch(newDestKey.branch());
      change.setDest(newDestKey);

      if (!input.keepAllVotes) {
        updateApprovals(ctx, update, psId, projectKey);
      }

      StringBuilder msgBuf = new StringBuilder();
      msgBuf.append("Change destination moved from ");
      msgBuf.append(changePrevDest.shortName());
      msgBuf.append(" to ");
      msgBuf.append(newDestKey.shortName());
      if (!Strings.isNullOrEmpty(input.message)) {
        msgBuf.append("\n\n");
        msgBuf.append(input.message);
      }
      ChangeMessage cmsg =
          ChangeMessagesUtil.newMessage(ctx, msgBuf.toString(), ChangeMessagesUtil.TAG_MOVE);
      cmUtil.addChangeMessage(update, cmsg);

      return true;
    }

    /**
     * We have a long discussion about how to deal with its votes after moving a change from one
     * branch to another. In the end, we think only keeping the veto votes is the best way since
     * it's simple for us and less confusing for our users. See the discussion in the following
     * proposal: https://gerrit-review.googlesource.com/c/gerrit/+/129171
     */
    private void updateApprovals(
        ChangeContext ctx, ChangeUpdate update, PatchSet.Id psId, Project.NameKey project)
        throws IOException {
      for (PatchSetApproval psa :
          approvalsUtil.byPatchSet(
              ctx.getNotes(), psId, ctx.getRevWalk(), ctx.getRepoView().getConfig())) {
        ProjectState projectState = projectCache.get(project).orElseThrow(illegalState(project));
        LabelType type = projectState.getLabelTypes(ctx.getNotes()).byLabel(psa.labelId());
        // Only keep veto votes, defined as votes where:
        // 1- the label function allows minimum values to block submission.
        // 2- the vote holds the minimum value.
        if (type == null || (type.isMaxNegative(psa) && type.getFunction().isBlock())) {
          continue;
        }

        // Remove votes from NoteDb.
        update.removeApprovalFor(psa.accountId(), psa.label());
      }
    }
  }

  @Override
  public UiAction.Description getDescription(ChangeResource rsrc) throws IOException {
    UiAction.Description description =
        new UiAction.Description()
            .setLabel("Move Change")
            .setTitle("Move change to a different branch")
            .setVisible(false);

    Change change = rsrc.getChange();
    if (!change.isNew()) {
      return description;
    }
    if (!projectCache
        .get(rsrc.getProject())
        .orElseThrow(illegalState(rsrc.getProject()))
        .statePermitsWrite()) {
      return description;
    }
    if (psUtil.isPatchSetLocked(rsrc.getNotes())) {
      return description;
    }
    return description.setVisible(
        and(
            permissionBackend.user(rsrc.getUser()).ref(change.getDest()).testCond(CREATE_CHANGE),
            rsrc.permissions().testCond(ABANDON)));
  }
}
