// 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.googlesource.gerrit.plugins.batch.ssh;

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.json.OutputFormat;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.project.NoSuchRefException;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.gerrit.util.cli.Options;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.batch.Batch;
import com.googlesource.gerrit.plugins.batch.BatchCloser;
import com.googlesource.gerrit.plugins.batch.cli.FastForwardOptions;
import com.googlesource.gerrit.plugins.batch.cli.MergeStrategyOption;
import com.googlesource.gerrit.plugins.batch.cli.PatchSetArgument;
import com.googlesource.gerrit.plugins.batch.util.MergeBranch;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;

@CommandMetaData(
    name = "merge-change",
    description = "Merge changes in the git repository to a batch")
public class MergeChangeCommand extends SshCommand {
  @Inject @Options public MergeStrategyOption strategy;
  @Inject @Options public FastForwardOptions fastForward;

  @Option(
      name = "--message",
      aliases = "-m",
      metaVar = "MESSAGE",
      usage = "commit message to use when applying a change")
  public String message;

  @Option(name = "--close", usage = "close batch on merge success")
  public boolean close;

  protected LinkedHashMap<PatchSet.Id, PatchSetArgument> patchSetArgumentsByPatchSet =
      new LinkedHashMap<>();

  @Argument(
      index = 0,
      required = true,
      multiValued = true,
      metaVar = "{CHANGE,PATCHSET}",
      usage = "list of patch sets to merge")
  protected void addPatchSetId(final String token) {
    PatchSetArgument psa = patchSetArgumentFactory.createForArgument(token);
    psa.ensureLatest();
    patchSetArgumentsByPatchSet.put(psa.patchSet.id(), psa);
  }

  @Inject protected PatchSetArgument.Factory patchSetArgumentFactory;
  @Inject protected MergeBranch.Factory mergeBranchFactory;
  @Inject protected BatchCloser batchCloser;
  @Inject protected GitRepositoryManager repoManager;
  protected Map<PatchSet.Id, List<ObjectId>> parentsByPsarg = new HashMap<>();

  @Override
  public void run() throws Exception {
    Batch batch = new Batch(user.getAccountId());
    String err = null;
    try {
      Resolver resolver = new Resolver(patchSetArgumentsByPatchSet.values());
      for (PatchSetArgument psarg : resolver.resolved) {
        err = "Couldn't merge change(" + psarg.patchSet + ") to batch(" + batch.id + ")";
        merge(batch, psarg.change, psarg.patchSet);
      }
      if (close) {
        err = "Could not close batch(" + batch.id + ")";
        batchCloser.close(batch);
      }
    } catch (Exception e) {
      String msg = e.getMessage();
      if (msg != null) {
        err += ": " + msg;
      }
      throw die(err);
    }
    batch.version = null;
    out.write((OutputFormat.JSON.newGson().toJson(batch) + "\n").getBytes(ENC));
    out.flush();
  }

  protected boolean isParentMergedInto(PatchSetArgument psarg, Iterable<ObjectId> sha1s)
      throws IOException, RepositoryNotFoundException {
    for (ObjectId sha1 : sha1s) {
      if (isParentMergedInto(psarg, sha1)) {
        return true;
      }
    }
    return false;
  }

  protected boolean isParentMergedInto(PatchSetArgument psarg, ObjectId sha1)
      throws IOException, RepositoryNotFoundException {
    List<ObjectId> parents = getParents(psarg);
    if (parents.isEmpty()) {
      return true;
    }
    for (ObjectId parent : parents) {
      Project.NameKey project = psarg.change.getDest().project();
      if (isMergedInto(project, parent, sha1)) {
        return true;
      }
    }
    return false;
  }

  public boolean isMergedInto(Project.NameKey project, ObjectId needle, ObjectId haystack)
      throws IOException {
    try (Repository repo = repoManager.openRepository(project);
        RevWalk walk = new RevWalk(repo)) {
      return walk.isMergedInto(walk.parseCommit(needle), walk.parseCommit(haystack));
    }
  }

  protected ObjectId getTip(BranchNameKey branch)
      throws IOException, NoSuchRefException, RepositoryNotFoundException {
    try (Repository repo = repoManager.openRepository(branch.project())) {
      Ref ref = repo.getRefDatabase().exactRef(branch.branch());
      if (ref == null) {
        throw new NoSuchRefException(branch.toString());
      }
      return ref.getObjectId();
    }
  }

  protected void merge(Batch batch, Change change, PatchSet ps)
      throws Exception, IOException, NoSuchRefException, UnloggedFailure {
    BranchNameKey branch = change.getDest();
    Batch.Destination dest = batch.getDestination(branch);
    dest.sha1 =
        mergeBranchFactory
            .create(
                branch,
                dest.sha1,
                ps.refName(),
                strategy.getMergeStrategy(),
                fastForward.getFastForwardMode(),
                message)
            .call()
            .getName();
    dest.add(ps.id());
  }

  /* A Resolver which ensures that changes are eligible to merge before
   * resolving them.  Once resolved, changes are ordered to minimize the
   * amount of merge commits required to merge them.
   */
  protected class Resolver {
    protected class ParentsNotOnBranchException extends Exception {
      private static final long serialVersionUID = 1L;

      protected ParentsNotOnBranchException(PatchSetArgument psarg) {
        super(
            "No Parent of "
                + psarg.patchSet
                + " is on its destination branch("
                + psarg.change.getDest()
                + ")");
      }
    }

    protected class Destination {
      List<PatchSetArgument> remaining = new ArrayList<>();
      Set<ObjectId> sources = new HashSet<>();

      Destination(BranchNameKey branch) throws IOException, NoSuchRefException {
        sources.add(getTip(branch));
      }
    }

    protected Map<BranchNameKey, Destination> destinationsByBranches = new HashMap<>();
    protected List<PatchSetArgument> resolved = new ArrayList<>();

    protected Resolver(Iterable<PatchSetArgument> psargs)
        throws Exception, IOException, NoSuchRefException, RepositoryNotFoundException {
      add(psargs);
      while (resolve()) {}
      for (Destination dest : destinationsByBranches.values()) {
        if (!dest.remaining.isEmpty()) {
          throw new ParentsNotOnBranchException(dest.remaining.get(0));
        }
      }
      Collections.reverse(resolved); // Reduces merges
    }

    protected boolean resolve() throws IOException, RepositoryNotFoundException {
      boolean found = false;
      for (Destination dest : destinationsByBranches.values()) {
        // If more dependencies are destined for the same branch than not,
        // then resolving a branch as much as possible will reduce the
        // total iterations required.
        while (resolve(dest)) {
          found = true;
        }
      }
      return found;
    }

    protected boolean resolve(Destination dest) throws IOException, RepositoryNotFoundException {
      boolean found = false;
      for (PatchSetArgument psarg : dest.remaining) {
        if (isParentMergedInto(psarg, dest.sources)) {
          found = true;
          resolved.add(psarg);
          dest.sources.add(psarg.patchSet.commitId());
        }
      }
      dest.remaining.removeAll(resolved);
      return found;
    }

    protected void add(Iterable<PatchSetArgument> psargs) throws IOException, NoSuchRefException {
      for (PatchSetArgument psarg : psargs) {
        add(psarg);
      }
    }

    protected void add(PatchSetArgument psarg) throws IOException, NoSuchRefException {
      BranchNameKey branch = psarg.change.getDest();
      Destination dest = getDestination(branch);
      dest.remaining.add(psarg);
    }

    protected Destination getDestination(BranchNameKey b) throws IOException, NoSuchRefException {
      Destination dest = destinationsByBranches.get(b);
      if (dest == null) {
        dest = new Destination(b);
        destinationsByBranches.put(b, dest);
      }
      return dest;
    }
  }

  protected List<ObjectId> getParents(PatchSetArgument psarg) throws IOException {
    PatchSet.Id id = psarg.patchSet.id();
    List<ObjectId> parents = parentsByPsarg.get(id);
    if (parents == null) {
      parents = loadParents(psarg);
      parentsByPsarg.put(id, parents);
    }
    return parents;
  }

  protected List<ObjectId> loadParents(PatchSetArgument psarg) throws IOException {
    try (Repository repo = repoManager.openRepository(psarg.change.getProject());
        RevWalk revWalk = new RevWalk(repo)) {
      List<ObjectId> parents = new ArrayList<>();
      ObjectId id = psarg.patchSet.commitId();
      RevCommit c = revWalk.parseCommit(id);
      for (RevCommit parent : c.getParents()) {
        parents.add(parent);
      }
      return parents;
    }
  }
}
