// Copyright (C) 2013 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.server.project.ProjectCache.illegalState;

import com.google.gerrit.common.data.SubmitTypeRecord;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.common.MergeableInfo;
import com.google.gerrit.extensions.restapi.AuthException;
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.RestReadView;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.change.MergeabilityCache;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.git.BranchOrderSection;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.project.SubmitRuleEvaluator;
import com.google.gerrit.server.project.SubmitRuleOptions;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Future;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.kohsuke.args4j.Option;

public class Mergeable implements RestReadView<RevisionResource> {
  @Option(
      name = "--other-branches",
      aliases = {"-o"},
      usage = "test mergeability for other branches too")
  private boolean otherBranches;

  private final GitRepositoryManager gitManager;
  private final ProjectCache projectCache;
  private final MergeUtil.Factory mergeUtilFactory;
  private final ChangeData.Factory changeDataFactory;
  private final ChangeIndexer indexer;
  private final MergeabilityCache cache;
  private final SubmitRuleEvaluator submitRuleEvaluator;

  @Inject
  Mergeable(
      GitRepositoryManager gitManager,
      ProjectCache projectCache,
      MergeUtil.Factory mergeUtilFactory,
      ChangeData.Factory changeDataFactory,
      ChangeIndexer indexer,
      MergeabilityCache cache,
      SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory) {
    this.gitManager = gitManager;
    this.projectCache = projectCache;
    this.mergeUtilFactory = mergeUtilFactory;
    this.changeDataFactory = changeDataFactory;
    this.indexer = indexer;
    this.cache = cache;
    submitRuleEvaluator = submitRuleEvaluatorFactory.create(SubmitRuleOptions.defaults());
  }

  public void setOtherBranches(boolean otherBranches) {
    this.otherBranches = otherBranches;
  }

  @Override
  public Response<MergeableInfo> apply(RevisionResource resource)
      throws AuthException, ResourceConflictException, BadRequestException, IOException {
    Change change = resource.getChange();
    PatchSet ps = resource.getPatchSet();
    MergeableInfo result = new MergeableInfo();

    if (!change.isNew()) {
      throw new ResourceConflictException("change is " + ChangeUtil.status(change));
    } else if (!ps.id().equals(change.currentPatchSetId())) {
      // Only the current revision is mergeable. Others always fail.
      return Response.ok(result);
    }

    ChangeData cd = changeDataFactory.create(resource.getNotes());
    result.submitType = getSubmitType(cd);

    try (Repository git = gitManager.openRepository(change.getProject())) {
      ObjectId commit = ps.commitId();
      Ref ref = git.getRefDatabase().exactRef(change.getDest().branch());
      ProjectState projectState =
          projectCache.get(change.getProject()).orElseThrow(illegalState(change.getProject()));
      String strategy = mergeUtilFactory.create(projectState).mergeStrategyName();
      result.strategy = strategy;
      result.mergeable = isMergable(git, change, commit, ref, result.submitType, strategy);

      if (otherBranches) {
        result.mergeableInto = new ArrayList<>();
        BranchOrderSection branchOrder = projectState.getBranchOrderSection();
        if (branchOrder != null) {
          int prefixLen = Constants.R_HEADS.length();
          List<String> names = branchOrder.getMoreStable(ref.getName());
          Map<String, Ref> refs =
              git.getRefDatabase().exactRef(names.toArray(new String[names.size()]));
          for (String n : names) {
            Ref other = refs.get(n);
            if (other == null) {
              continue;
            }
            if (cache.get(commit, other, SubmitType.CHERRY_PICK, strategy, change.getDest(), git)) {
              result.mergeableInto.add(other.getName().substring(prefixLen));
            }
          }
        }
      }
    }
    return Response.ok(result);
  }

  private SubmitType getSubmitType(ChangeData cd) throws ResourceConflictException {
    SubmitTypeRecord rec = submitRuleEvaluator.getSubmitType(cd);
    if (rec.status != SubmitTypeRecord.Status.OK) {
      throw new ResourceConflictException("submit type rule error: " + rec.errorMessage);
    }
    return rec.type;
  }

  private boolean isMergable(
      Repository git,
      Change change,
      ObjectId commit,
      Ref ref,
      SubmitType submitType,
      String strategy) {
    if (commit == null) {
      return false;
    }

    Boolean old = cache.getIfPresent(commit, ref, submitType, strategy);
    if (old != null) {
      return old;
    }
    return refresh(change, commit, ref, submitType, strategy, git, old);
  }

  private boolean refresh(
      final Change change,
      ObjectId commit,
      final Ref ref,
      SubmitType type,
      String strategy,
      Repository git,
      Boolean old) {
    boolean mergeable = cache.get(commit, ref, type, strategy, change.getDest(), git);
    // TODO(dborowitz): Include something else in the change ETag that it's possible to bump here,
    // such as cache or secondary index update time.
    if (!Objects.equals(mergeable, old)) {
      @SuppressWarnings("unused")
      Future<?> possiblyIgnoredError = indexer.indexAsync(change.getProject(), change.getId());
    }
    return mergeable;
  }
}
