// Copyright (C) 2022 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.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.changes.RebaseInput;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.RebaseChainInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
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.CurrentUser;
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.change.GetRelatedChangesUtil;
import com.google.gerrit.server.change.NotifyResolver;
import com.google.gerrit.server.change.RebaseChangeOp;
import com.google.gerrit.server.change.RebaseUtil;
import com.google.gerrit.server.change.RelatedChangesSorter.PatchSetData;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.permissions.ChangePermission;
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.query.change.ChangeData;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;

/** Rest API for rebasing an ancestry chain of changes. */
@Singleton
public class RebaseChain
    implements RestModifyView<ChangeResource, RebaseInput>, UiAction<ChangeResource> {
  private static final ImmutableSet<ListChangesOption> OPTIONS =
      Sets.immutableEnumSet(ListChangesOption.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT);

  private final GitRepositoryManager repoManager;
  private final RebaseUtil rebaseUtil;
  private final GetRelatedChangesUtil getRelatedChangesUtil;
  private final ChangeResource.Factory changeResourceFactory;
  private final ChangeData.Factory changeDataFactory;
  private final PermissionBackend permissionBackend;
  private final BatchUpdate.Factory updateFactory;
  private final ChangeNotes.Factory notesFactory;
  private final ProjectCache projectCache;
  private final PatchSetUtil patchSetUtil;
  private final ChangeJson.Factory json;
  private final RebaseMetrics rebaseMetrics;

  @Inject
  RebaseChain(
      GitRepositoryManager repoManager,
      RebaseUtil rebaseUtil,
      GetRelatedChangesUtil getRelatedChangesUtil,
      ChangeResource.Factory changeResourceFactory,
      ChangeData.Factory changeDataFactory,
      PermissionBackend permissionBackend,
      BatchUpdate.Factory updateFactory,
      ChangeNotes.Factory notesFactory,
      ProjectCache projectCache,
      PatchSetUtil patchSetUtil,
      ChangeJson.Factory json,
      RebaseMetrics rebaseMetrics) {
    this.repoManager = repoManager;
    this.getRelatedChangesUtil = getRelatedChangesUtil;
    this.changeDataFactory = changeDataFactory;
    this.rebaseUtil = rebaseUtil;
    this.changeResourceFactory = changeResourceFactory;
    this.permissionBackend = permissionBackend;
    this.updateFactory = updateFactory;
    this.notesFactory = notesFactory;
    this.projectCache = projectCache;
    this.patchSetUtil = patchSetUtil;
    this.json = json;
    this.rebaseMetrics = rebaseMetrics;
  }

  @Override
  public Response<RebaseChainInfo> apply(ChangeResource tipRsrc, RebaseInput input)
      throws IOException, PermissionBackendException, RestApiException, UpdateException {
    if (input.onBehalfOfUploader) {
      tipRsrc.permissions().check(ChangePermission.REBASE_ON_BEHALF_OF_UPLOADER);
      if (input.allowConflicts) {
        throw new BadRequestException(
            "allow_conflicts and on_behalf_of_uploader are mutually exclusive");
      }
    } else {
      tipRsrc.permissions().check(ChangePermission.REBASE);
    }

    Project.NameKey project = tipRsrc.getProject();
    projectCache.get(project).orElseThrow(illegalState(project)).checkStatePermitsWrite();

    CurrentUser user = tipRsrc.getUser();

    boolean anyRebaseOnBehalfOfUploader = false;
    List<Change.Id> upToDateAncestors = new ArrayList<>();
    Map<Change.Id, RebaseChangeOp> rebaseOps = new LinkedHashMap<>();
    try (RefUpdateContext ctx = RefUpdateContext.open(CHANGE_MODIFICATION)) {
      try (Repository repo = repoManager.openRepository(project);
          ObjectInserter oi = repo.newObjectInserter();
          ObjectReader reader = oi.newReader();
          RevWalk rw = CodeReviewCommit.newRevWalk(reader);
          BatchUpdate bu = updateFactory.create(project, user, TimeUtil.now())) {
        List<PatchSetData> chain = getChainForCurrentPatchSet(tipRsrc);

        boolean ancestorsAreUpToDate = true;
        for (int i = 0; i < chain.size(); i++) {
          ChangeData changeData = chain.get(i).data();
          PatchSet ps = patchSetUtil.current(changeData.notes());
          if (ps == null) {
            throw new IllegalStateException(
                "current revision is missing for change " + changeData.getId());
          }

          RevisionResource revRsrc =
              new RevisionResource(changeResourceFactory.create(changeData, user), ps);
          if (input.onBehalfOfUploader
              && !revRsrc.getPatchSet().uploader().equals(revRsrc.getAccountId())) {
            revRsrc = rebaseUtil.onBehalfOf(revRsrc, input);
            revRsrc.permissions().check(ChangePermission.REBASE_ON_BEHALF_OF_UPLOADER);
            anyRebaseOnBehalfOfUploader = true;
          } else {
            revRsrc.permissions().check(ChangePermission.REBASE);
          }
          rebaseUtil.verifyRebasePreconditions(rw, changeData.notes(), ps);

          boolean isUpToDate = false;
          RebaseChangeOp rebaseOp = null;
          if (i == 0) {
            ObjectId desiredBase =
                rebaseUtil.parseOrFindBaseRevision(
                    repo, rw, permissionBackend, revRsrc, input, false);
            if (currentBase(rw, ps).equals(desiredBase)) {
              isUpToDate = true;
            } else {
              rebaseOp = rebaseUtil.getRebaseOp(revRsrc, input, desiredBase);
            }
          } else {
            if (ancestorsAreUpToDate) {
              ObjectId latestCommittedBase =
                  PatchSetUtil.getCurrentCommittedRevCommit(
                      project, rw, notesFactory, chain.get(i - 1).id());
              isUpToDate = currentBase(rw, ps).equals(latestCommittedBase);
            }
            if (!isUpToDate) {
              rebaseOp = rebaseUtil.getRebaseOp(revRsrc, input, chain.get(i - 1).id());
            }
          }

          if (isUpToDate) {
            upToDateAncestors.add(changeData.getId());
            continue;
          }
          ancestorsAreUpToDate = false;
          bu.addOp(revRsrc.getChange().getId(), revRsrc.getUser(), rebaseOp);
          rebaseOps.put(revRsrc.getChange().getId(), rebaseOp);
        }

        if (ancestorsAreUpToDate) {
          throw new ResourceConflictException("The whole chain is already up to date.");
        }

        bu.setNotify(NotifyResolver.Result.none());
        bu.setRepository(repo, rw, oi);
        bu.execute();
      }
    }

    rebaseMetrics.countRebaseChain(anyRebaseOnBehalfOfUploader, input.allowConflicts);

    RebaseChainInfo res = new RebaseChainInfo();
    res.rebasedChanges = new ArrayList<>();
    ChangeJson changeJson = json.create(OPTIONS);
    for (Change.Id c : upToDateAncestors) {
      res.rebasedChanges.add(changeJson.format(project, c));
    }
    for (Map.Entry<Change.Id, RebaseChangeOp> e : rebaseOps.entrySet()) {
      Change.Id id = e.getKey();
      RebaseChangeOp op = e.getValue();
      ChangeInfo changeInfo = changeJson.format(project, id);
      changeInfo.containsGitConflicts =
          !op.getRebasedCommit().getFilesWithGitConflicts().isEmpty() ? true : null;
      res.rebasedChanges.add(changeInfo);
    }
    if (res.rebasedChanges.stream()
        .anyMatch(i -> i.containsGitConflicts != null && i.containsGitConflicts)) {
      res.containsGitConflicts = true;
    }
    return Response.ok(res);
  }

  @Override
  public Description getDescription(ChangeResource tipRsrc) throws Exception {
    UiAction.Description description =
        new UiAction.Description()
            .setLabel("Rebase Chain")
            .setTitle(
                "Rebase the ancestry chain onto the tip of the target branch. Makes you the "
                    + "uploader of the changes which can affect validity of approvals.")
            .setVisible(false);

    Change tip = tipRsrc.getChange();
    if (!tip.isNew()) {
      return description;
    }
    if (!projectCache
        .get(tipRsrc.getProject())
        .orElseThrow(illegalState(tipRsrc.getProject()))
        .statePermitsWrite()) {
      return description;
    }

    if (patchSetUtil.isPatchSetLocked(tipRsrc.getNotes())) {
      return description;
    }

    boolean visible = true;
    boolean enabled;
    try (Repository repo = repoManager.openRepository(tipRsrc.getProject());
        RevWalk rw = new RevWalk(repo)) {
      List<PatchSetData> chain = getChainForCurrentPatchSet(tipRsrc);
      if (chain.size() <= 1) {
        return description;
      }
      PatchSetData oldestAncestor = chain.get(0);
      enabled =
          rebaseUtil.canRebase(
              oldestAncestor.patchSet(), oldestAncestor.data().change().getDest(), repo, rw);

      ImmutableList<RevisionResource> chainAsRevisionResources =
          chain.stream()
              .map(
                  ps ->
                      new RevisionResource(
                          changeResourceFactory.create(ps.data(), tipRsrc.getUser()),
                          ps.patchSet()))
              .collect(toImmutableList());

      boolean canRebase =
          chainAsRevisionResources.stream()
              .allMatch(psRsrc -> psRsrc.permissions().testOrFalse(ChangePermission.REBASE));
      boolean canRebaseOnBehalfOfUploader =
          chainAsRevisionResources.stream()
              .allMatch(
                  psRsrc ->
                      psRsrc
                          .permissions()
                          .testOrFalse(ChangePermission.REBASE_ON_BEHALF_OF_UPLOADER));

      if (!canRebase && !canRebaseOnBehalfOfUploader) {
        visible = false;
      } else {
        for (RevisionResource psRsrc : chainAsRevisionResources) {
          if (patchSetUtil.isPatchSetLocked(psRsrc.getNotes())
              || !RebaseUtil.hasOneParent(rw, psRsrc.getPatchSet())) {
            enabled = false;
            break;
          }
        }
      }

      return description
          .setVisible(visible)
          .setOption("rebase", canRebase)
          .setOption("rebase_on_behalf_of_uploader", canRebaseOnBehalfOfUploader)
          .setEnabled(enabled);
    }
  }

  private ObjectId currentBase(RevWalk rw, PatchSet ps) throws IOException {
    return rw.parseCommit(ps.commitId()).getParent(0);
  }

  private List<PatchSetData> getChainForCurrentPatchSet(ChangeResource rsrc)
      throws PermissionBackendException, IOException {
    List<PatchSetData> ancestors =
        Lists.reverse(
            getRelatedChangesUtil.getAncestors(
                changeDataFactory.create(rsrc.getNotes()),
                patchSetUtil.current(rsrc.getNotes()),
                true));
    int eldestOpenAncestor = 0;
    for (PatchSetData ps : ancestors) {
      if (ps.data().change().isMerged()) {
        eldestOpenAncestor++;
      }
    }
    return ancestors.subList(eldestOpenAncestor, ancestors.size());
  }
}
