// Copyright (C) 2012 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.git.ObjectIds.abbreviateName;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static java.util.stream.Collectors.joining;

import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.UsedAt;
import com.google.gerrit.common.data.ParameterizedString;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.SubmitTypeRecord;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.changes.SubmitInput;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.restapi.AuthException;
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.restapi.UnprocessableEntityException;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.server.BranchUtil;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
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.project.ProjectState;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.submit.ChangeSet;
import com.google.gerrit.server.submit.MergeOp;
import com.google.gerrit.server.submit.MergeSuperSet;
import com.google.gerrit.server.update.UpdateException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
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 Submit
    implements RestModifyView<RevisionResource, SubmitInput>, UiAction<RevisionResource> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final String DEFAULT_TOOLTIP = "Submit patch set ${patchSet} into ${branch}";
  private static final String DEFAULT_TOOLTIP_ANCESTORS =
      "Submit patch set ${patchSet} and ancestors (${submitSize} changes "
          + "altogether) into ${branch}";
  private static final String DEFAULT_TOPIC_TOOLTIP =
      "Submit all ${topicSize} changes of the same topic "
          + "(${submitSize} changes including ancestors and other "
          + "changes related by topic)";
  private static final String BLOCKED_HIDDEN_SUBMIT_TOOLTIP =
      "This change depends on other hidden changes which are not ready";
  private static final String CLICK_FAILURE_TOOLTIP = "Clicking the button would fail";
  private static final String CHANGE_UNMERGEABLE = "Problems with integrating this change";

  private final GitRepositoryManager repoManager;
  private final PermissionBackend permissionBackend;
  private final Provider<MergeOp> mergeOpProvider;
  private final Provider<MergeSuperSet> mergeSuperSet;
  private final AccountResolver accountResolver;
  private final String label;
  private final String labelWithParents;
  private final ParameterizedString titlePattern;
  private final ParameterizedString titlePatternWithAncestors;
  private final String submitTopicLabel;
  private final ParameterizedString submitTopicTooltip;
  private final boolean submitWholeTopic;
  private final Provider<InternalChangeQuery> queryProvider;
  private final PatchSetUtil psUtil;
  private final ProjectCache projectCache;
  private final ChangeJson.Factory json;

  @Inject
  Submit(
      GitRepositoryManager repoManager,
      PermissionBackend permissionBackend,
      Provider<MergeOp> mergeOpProvider,
      Provider<MergeSuperSet> mergeSuperSet,
      AccountResolver accountResolver,
      @GerritServerConfig Config cfg,
      Provider<InternalChangeQuery> queryProvider,
      PatchSetUtil psUtil,
      ProjectCache projectCache,
      ChangeJson.Factory json) {
    this.repoManager = repoManager;
    this.permissionBackend = permissionBackend;
    this.mergeOpProvider = mergeOpProvider;
    this.mergeSuperSet = mergeSuperSet;
    this.accountResolver = accountResolver;
    this.label =
        MoreObjects.firstNonNull(
            Strings.emptyToNull(cfg.getString("change", null, "submitLabel")), "Submit");
    this.labelWithParents =
        MoreObjects.firstNonNull(
            Strings.emptyToNull(cfg.getString("change", null, "submitLabelWithParents")),
            "Submit including parents");
    this.titlePattern =
        new ParameterizedString(
            MoreObjects.firstNonNull(
                cfg.getString("change", null, "submitTooltip"), DEFAULT_TOOLTIP));
    this.titlePatternWithAncestors =
        new ParameterizedString(
            MoreObjects.firstNonNull(
                cfg.getString("change", null, "submitTooltipAncestors"),
                DEFAULT_TOOLTIP_ANCESTORS));
    submitWholeTopic = MergeSuperSet.wholeTopicEnabled(cfg);
    this.submitTopicLabel =
        MoreObjects.firstNonNull(
            Strings.emptyToNull(cfg.getString("change", null, "submitTopicLabel")),
            "Submit whole topic");
    this.submitTopicTooltip =
        new ParameterizedString(
            MoreObjects.firstNonNull(
                cfg.getString("change", null, "submitTopicTooltip"), DEFAULT_TOPIC_TOOLTIP));
    this.queryProvider = queryProvider;
    this.psUtil = psUtil;
    this.projectCache = projectCache;
    this.json = json;
  }

  @Override
  public Response<ChangeInfo> apply(RevisionResource rsrc, @Nullable SubmitInput input)
      throws RestApiException, RepositoryNotFoundException, IOException, PermissionBackendException,
          UpdateException, ConfigInvalidException {
    if (input == null) {
      input = new SubmitInput();
    }
    input.onBehalfOf = Strings.emptyToNull(input.onBehalfOf);
    IdentifiedUser submitter;
    if (input.onBehalfOf != null) {
      submitter = onBehalfOf(rsrc, input);
    } else {
      rsrc.permissions().check(ChangePermission.SUBMIT);
      submitter = rsrc.getUser().asIdentifiedUser();
    }
    projectCache
        .get(rsrc.getProject())
        .orElseThrow(illegalState(rsrc.getProject()))
        .checkStatePermitsWrite();

    return Response.ok(json.noOptions().format(mergeChange(rsrc, submitter, input)));
  }

  @UsedAt(UsedAt.Project.GOOGLE)
  public Change mergeChange(RevisionResource rsrc, IdentifiedUser submitter, SubmitInput input)
      throws RestApiException, IOException, UpdateException, ConfigInvalidException,
          PermissionBackendException {
    Change change = rsrc.getChange();
    if (!change.isNew()) {
      throw new ResourceConflictException("change is " + ChangeUtil.status(change));
    } else if (!BranchUtil.branchExists(repoManager, change.getDest())) {
      throw new ResourceConflictException(
          String.format("destination branch \"%s\" not found.", change.getDest().branch()));
    } else if (!rsrc.getPatchSet().id().equals(change.currentPatchSetId())) {
      // TODO Allow submitting non-current revision by changing the current.
      throw new ResourceConflictException(
          String.format(
              "revision %s is not current revision", rsrc.getPatchSet().commitId().name()));
    }

    try (MergeOp op = mergeOpProvider.get()) {
      Change updatedChange;

      updatedChange = op.merge(change, submitter, true, input, false);
      if (updatedChange.isMerged()) {
        return updatedChange;
      }

      throw new IllegalStateException(
          String.format(
              "change %s of project %s unexpectedly had status %s after submit attempt",
              updatedChange.getId(), updatedChange.getProject(), updatedChange.getStatus()));
    }
  }

  /**
   * Returns a message describing what prevents the current change from being submitted - or null.
   * This method only considers parent changes, and changes in the same topic. The caller is
   * responsible for making sure the current change to be submitted can indeed be submitted
   * (permissions, submit rules, is not a WIP...)
   *
   * @param cd the change the user is currently looking at
   * @param cs set of changes to be submitted at once
   * @param user the user who is checking to submit
   * @return a reason why any of the changes is not submittable or null
   */
  @Nullable
  private String problemsForSubmittingChangeset(ChangeData cd, ChangeSet cs, CurrentUser user) {
    try {
      if (cs.furtherHiddenChanges()) {
        logger.atFine().log(
            "Change %d cannot be submitted by user %s because it depends on hidden changes: %s",
            cd.getId().get(), user.getLoggableName(), cs.nonVisibleChanges());
        return BLOCKED_HIDDEN_SUBMIT_TOOLTIP;
      }
      for (ChangeData c : cs.changes()) {
        Set<ChangePermission> can =
            permissionBackend
                .user(user)
                .change(c)
                .test(EnumSet.of(ChangePermission.READ, ChangePermission.SUBMIT));
        if (!can.contains(ChangePermission.READ)) {
          logger.atFine().log(
              "Change %d cannot be submitted by user %s because it depends on change %d which the user cannot read",
              cd.getId().get(), user.getLoggableName(), c.getId().get());
          return BLOCKED_HIDDEN_SUBMIT_TOOLTIP;
        }
        if (!can.contains(ChangePermission.SUBMIT)) {
          return "You don't have permission to submit change " + c.getId();
        }
        if (c.change().isWorkInProgress()) {
          return "Change " + c.getId() + " is marked work in progress";
        }
        try {
          // The data in the change index may be stale (e.g. if submit requirements have been
          // changed). For that one change for which the submit action is computed, use the
          // freshly loaded ChangeData instance 'cd' instead of the potentially stale ChangeData
          // instance 'c' that was loaded from the index. This makes a difference if the ChangeSet
          // 'cs' only contains this one single change. If the ChangeSet contains further changes
          // those may still be stale.
          MergeOp.checkSubmitRequirements(cd.getId().equals(c.getId()) ? cd : c);
        } catch (ResourceConflictException e) {
          return (c.getId() == cd.getId())
              ? String.format("Change %s is not ready: %s", cd.getId(), e.getMessage())
              : String.format(
                  "Change %s must be submitted with change %s but %s is not ready: %s",
                  cd.getId(), c.getId(), c.getId(), e.getMessage());
        }
      }

      Collection<ChangeData> unmergeable = unmergeableChanges(cs);
      if (unmergeable == null) {
        return CLICK_FAILURE_TOOLTIP;
      } else if (!unmergeable.isEmpty()) {
        for (ChangeData c : unmergeable) {
          if (c.change().getKey().equals(cd.change().getKey())) {
            return CHANGE_UNMERGEABLE;
          }
        }

        return "Problems with change(s): "
            + unmergeable.stream().map(c -> c.getId().toString()).collect(joining(", "));
      }
    } catch (PermissionBackendException | IOException e) {
      logger.atSevere().withCause(e).log("Error checking if change is submittable");
      throw new StorageException("Could not determine problems for the change", e);
    }
    return null;
  }

  @Nullable
  @Override
  public UiAction.Description getDescription(RevisionResource resource)
      throws IOException, PermissionBackendException {
    Change change = resource.getChange();
    if (!change.isNew() || !resource.isCurrent()) {
      return null; // submit not visible
    }
    if (!projectCache
        .get(resource.getProject())
        .map(ProjectState::statePermitsWrite)
        .orElse(false)) {
      return null; // submit not visible
    }

    ChangeData cd = resource.getChangeResource().getChangeData();
    try {
      MergeOp.checkSubmitRequirements(cd);
    } catch (ResourceConflictException e) {
      return null; // submit not visible
    }

    ChangeSet cs =
        mergeSuperSet
            .get()
            .completeChangeSet(cd.change(), resource.getUser(), /*includingTopicClosure= */ false);
    String topic = change.getTopic();
    int topicSize = 0;
    if (!Strings.isNullOrEmpty(topic)) {
      topicSize = queryProvider.get().noFields().byTopicOpen(topic).size();
    }
    boolean treatWithTopic = submitWholeTopic && !Strings.isNullOrEmpty(topic) && topicSize > 1;

    String submitProblems = problemsForSubmittingChangeset(cd, cs, resource.getUser());

    if (submitProblems != null) {
      return new UiAction.Description()
          .setLabel(treatWithTopic ? submitTopicLabel : (cs.size() > 1) ? labelWithParents : label)
          .setTitle(submitProblems)
          .setVisible(true)
          .setEnabled(false);
    }

    // Recheck mergeability rather than using value stored in the index, which may be stale.
    // TODO(dborowitz): This is ugly; consider providing a way to not read stored fields from the
    // index in the first place.
    // cd.setMergeable(null);
    // That was done in unmergeableChanges which was called by problemsForSubmittingChangeset, so
    // now it is safe to read from the cache, as it yields the same result.
    Boolean enabled = cd.isMergeable();

    if (treatWithTopic) {
      Map<String, String> params =
          ImmutableMap.of(
              "topicSize", String.valueOf(topicSize),
              "submitSize", String.valueOf(cs.size()));
      return new UiAction.Description()
          .setLabel(submitTopicLabel)
          .setTitle(Strings.emptyToNull(submitTopicTooltip.replace(params)))
          .setVisible(true)
          .setEnabled(Boolean.TRUE.equals(enabled));
    }
    Map<String, String> params =
        ImmutableMap.of(
            "patchSet", String.valueOf(resource.getPatchSet().number()),
            "branch", change.getDest().shortName(),
            "commit", abbreviateName(resource.getPatchSet().commitId()),
            "submitSize", String.valueOf(cs.size()));
    ParameterizedString tp = cs.size() > 1 ? titlePatternWithAncestors : titlePattern;
    return new UiAction.Description()
        .setLabel(cs.size() > 1 ? labelWithParents : label)
        .setTitle(Strings.emptyToNull(tp.replace(params)))
        .setVisible(true)
        .setEnabled(Boolean.TRUE.equals(enabled));
  }

  @Nullable
  public Collection<ChangeData> unmergeableChanges(ChangeSet cs) throws IOException {
    Set<ChangeData> mergeabilityMap = new HashSet<>();
    Set<ObjectId> outDatedPatchsets = new HashSet<>();
    for (ChangeData change : cs.changes()) {
      mergeabilityMap.add(change);
      // Add all the patchsets commit ids except the current patchset.
      outDatedPatchsets.addAll(
          change.notes().getPatchSets().values().stream()
              .map(p -> p.commitId())
              .collect(Collectors.toSet()));
      outDatedPatchsets.remove(change.currentPatchSet().commitId());
    }

    ListMultimap<BranchNameKey, ChangeData> cbb = cs.changesByBranch();
    for (BranchNameKey branch : cbb.keySet()) {
      Collection<ChangeData> targetBranch = cbb.get(branch);
      HashMap<Change.Id, RevCommit> commits = findCommits(targetBranch, branch.project());

      Set<ObjectId> allParents = Sets.newHashSetWithExpectedSize(cs.size());
      for (RevCommit commit : commits.values()) {
        for (RevCommit parent : commit.getParents()) {
          allParents.add(parent.getId());
        }
      }
      for (ChangeData change : targetBranch) {

        RevCommit commit = commits.get(change.getId());
        boolean isMergeCommit = commit.getParentCount() > 1;
        boolean isLastInChain = !allParents.contains(commit.getId());
        if (Arrays.stream(commit.getParents()).anyMatch(c -> outDatedPatchsets.contains(c.getId()))
            && !isCherryPickSubmit(change)) {
          // Found a parent that depends on an outdated patchset and the submit strategy is not
          // cherry-pick.
          continue;
        }
        // Recheck mergeability rather than using value stored in the index,
        // which may be stale.
        // TODO(dborowitz): This is ugly; consider providing a way to not read
        // stored fields from the index in the first place.
        change.setMergeable(null);
        Boolean mergeable = change.isMergeable();
        if (mergeable == null) {
          // Skip whole check, cannot determine if mergeable
          return null;
        }
        if (mergeable) {
          mergeabilityMap.remove(change);
        }

        if (isLastInChain && isMergeCommit && mergeable) {
          for (ChangeData c : targetBranch) {
            mergeabilityMap.remove(c);
          }
          break;
        }
      }
    }
    return mergeabilityMap;
  }

  private boolean isCherryPickSubmit(ChangeData changeData) {
    SubmitTypeRecord submitTypeRecord = changeData.submitTypeRecord();
    return submitTypeRecord.isOk() && submitTypeRecord.type == SubmitType.CHERRY_PICK;
  }

  private HashMap<Change.Id, RevCommit> findCommits(
      Collection<ChangeData> changes, Project.NameKey project) throws IOException {
    HashMap<Change.Id, RevCommit> commits = new HashMap<>();
    try (Repository repo = repoManager.openRepository(project);
        RevWalk walk = new RevWalk(repo)) {
      for (ChangeData change : changes) {
        RevCommit commit = walk.parseCommit(psUtil.current(change.notes()).commitId());
        commits.put(change.getId(), commit);
      }
    }
    return commits;
  }

  private IdentifiedUser onBehalfOf(RevisionResource rsrc, SubmitInput in)
      throws AuthException, UnprocessableEntityException, PermissionBackendException, IOException,
          ConfigInvalidException {
    PermissionBackend.ForChange perm = rsrc.permissions();
    perm.check(ChangePermission.SUBMIT);
    perm.check(ChangePermission.SUBMIT_AS);

    CurrentUser caller = rsrc.getUser();
    IdentifiedUser submitter =
        accountResolver.resolve(in.onBehalfOf).asUniqueUserOnBehalfOf(caller);
    try {
      permissionBackend.user(submitter).change(rsrc.getNotes()).check(ChangePermission.READ);
    } catch (AuthException e) {
      throw new UnprocessableEntityException(
          String.format("on_behalf_of account %s cannot see change", submitter.getAccountId()), e);
    }
    return submitter;
  }

  public static class CurrentRevision implements RestModifyView<ChangeResource, SubmitInput> {
    private final Submit submit;
    private final PatchSetUtil psUtil;

    @Inject
    CurrentRevision(Submit submit, PatchSetUtil psUtil) {
      this.submit = submit;
      this.psUtil = psUtil;
    }

    @Override
    public Response<ChangeInfo> apply(ChangeResource rsrc, SubmitInput input) throws Exception {
      PatchSet ps = psUtil.current(rsrc.getNotes());
      if (ps == null) {
        throw new ResourceConflictException("current revision is missing");
      }

      return submit.apply(new RevisionResource(rsrc, ps), input);
    }
  }
}
