// 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.change;

import static com.google.common.base.Preconditions.checkState;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Ordering;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevFlag;
import org.eclipse.jgit.revwalk.RevWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Helper to sort {@link ChangeData}s based on {@link RevWalk} ordering.
 *
 * <p>Split changes by project, and map each change to a single commit based on the latest patch
 * set. The set of patch sets considered may be limited by calling {@link
 * #includePatchSets(Iterable)}. Perform a standard {@link RevWalk} on each project repository, do
 * an approximate topo sort, and record the order in which each change's commit is seen.
 *
 * <p>Once an order within each project is determined, groups of changes are sorted based on the
 * project name. This is slightly more stable than sorting on something like the commit or change
 * timestamp, as it will not unexpectedly reorder large groups of changes on subsequent calls if one
 * of the changes was updated.
 */
public class WalkSorter {
  private static final Logger log = LoggerFactory.getLogger(WalkSorter.class);

  private static final Ordering<List<PatchSetData>> PROJECT_LIST_SORTER =
      Ordering.natural()
          .nullsFirst()
          .onResultOf(
              (List<PatchSetData> in) -> {
                if (in == null || in.isEmpty()) {
                  return null;
                }
                try {
                  return in.get(0).data().change().getProject();
                } catch (OrmException e) {
                  throw new IllegalStateException(e);
                }
              });

  private final GitRepositoryManager repoManager;
  private final Set<PatchSet.Id> includePatchSets;
  private boolean retainBody;

  @Inject
  WalkSorter(GitRepositoryManager repoManager) {
    this.repoManager = repoManager;
    includePatchSets = new HashSet<>();
  }

  public WalkSorter includePatchSets(Iterable<PatchSet.Id> patchSets) {
    Iterables.addAll(includePatchSets, patchSets);
    return this;
  }

  public WalkSorter setRetainBody(boolean retainBody) {
    this.retainBody = retainBody;
    return this;
  }

  public Iterable<PatchSetData> sort(Iterable<ChangeData> in) throws OrmException, IOException {
    ListMultimap<Project.NameKey, ChangeData> byProject =
        MultimapBuilder.hashKeys().arrayListValues().build();
    for (ChangeData cd : in) {
      byProject.put(cd.change().getProject(), cd);
    }

    List<List<PatchSetData>> sortedByProject = new ArrayList<>(byProject.keySet().size());
    for (Map.Entry<Project.NameKey, Collection<ChangeData>> e : byProject.asMap().entrySet()) {
      sortedByProject.add(sortProject(e.getKey(), e.getValue()));
    }
    Collections.sort(sortedByProject, PROJECT_LIST_SORTER);
    return Iterables.concat(sortedByProject);
  }

  private List<PatchSetData> sortProject(Project.NameKey project, Collection<ChangeData> in)
      throws OrmException, IOException {
    try (Repository repo = repoManager.openRepository(project);
        RevWalk rw = new RevWalk(repo)) {
      rw.setRetainBody(retainBody);
      ListMultimap<RevCommit, PatchSetData> byCommit = byCommit(rw, in);
      if (byCommit.isEmpty()) {
        return ImmutableList.of();
      } else if (byCommit.size() == 1) {
        return ImmutableList.of(byCommit.values().iterator().next());
      }

      // Walk from all patch set SHA-1s, and terminate as soon as we've found
      // everything we're looking for. This is equivalent to just sorting the
      // list of commits by the RevWalk's configured order.
      //
      // Partially topo sort the list, ensuring no parent is emitted before a
      // direct child that is also in the input set. This preserves the stable,
      // expected sort in the case where many commits share the same timestamp,
      // e.g. a quick rebase. It also avoids JGit's topo sort, which slurps all
      // interesting commits at the beginning, which is a problem since we don't
      // know which commits to mark as uninteresting. Finding a reasonable set
      // of commits to mark uninteresting (the "rootmost" set) is at least as
      // difficult as just implementing this partial topo sort ourselves.
      //
      // (This is slightly less efficient than JGit's topo sort, which uses a
      // private in-degree field in RevCommit rather than multimaps. We assume
      // the input size is small enough that this is not an issue.)

      Set<RevCommit> commits = byCommit.keySet();
      ListMultimap<RevCommit, RevCommit> children = collectChildren(commits);
      ListMultimap<RevCommit, RevCommit> pending =
          MultimapBuilder.hashKeys().arrayListValues().build();
      Deque<RevCommit> todo = new ArrayDeque<>();

      RevFlag done = rw.newFlag("done");
      markStart(rw, commits);
      int expected = commits.size();
      int found = 0;
      RevCommit c;
      List<PatchSetData> result = new ArrayList<>(expected);
      while (found < expected && (c = rw.next()) != null) {
        if (!commits.contains(c)) {
          continue;
        }
        todo.clear();
        todo.add(c);
        int i = 0;
        while (!todo.isEmpty()) {
          // Sanity check: we can't pop more than N pending commits, otherwise
          // we have an infinite loop due to programmer error or something.
          checkState(++i <= commits.size(), "Too many pending steps while sorting %s", commits);
          RevCommit t = todo.removeFirst();
          if (t.has(done)) {
            continue;
          }
          boolean ready = true;
          for (RevCommit child : children.get(t)) {
            if (!child.has(done)) {
              pending.put(child, t);
              ready = false;
            }
          }
          if (ready) {
            found += emit(t, byCommit, result, done);
            todo.addAll(pending.get(t));
          }
        }
      }
      return result;
    }
  }

  private static ListMultimap<RevCommit, RevCommit> collectChildren(Set<RevCommit> commits) {
    ListMultimap<RevCommit, RevCommit> children =
        MultimapBuilder.hashKeys().arrayListValues().build();
    for (RevCommit c : commits) {
      for (RevCommit p : c.getParents()) {
        if (commits.contains(p)) {
          children.put(p, c);
        }
      }
    }
    return children;
  }

  private static int emit(
      RevCommit c,
      ListMultimap<RevCommit, PatchSetData> byCommit,
      List<PatchSetData> result,
      RevFlag done) {
    if (c.has(done)) {
      return 0;
    }
    c.add(done);
    Collection<PatchSetData> psds = byCommit.get(c);
    if (!psds.isEmpty()) {
      result.addAll(psds);
      return 1;
    }
    return 0;
  }

  private ListMultimap<RevCommit, PatchSetData> byCommit(RevWalk rw, Collection<ChangeData> in)
      throws OrmException, IOException {
    ListMultimap<RevCommit, PatchSetData> byCommit =
        MultimapBuilder.hashKeys(in.size()).arrayListValues(1).build();
    for (ChangeData cd : in) {
      PatchSet maxPs = null;
      for (PatchSet ps : cd.patchSets()) {
        if (shouldInclude(ps) && (maxPs == null || ps.getId().get() > maxPs.getId().get())) {
          maxPs = ps;
        }
      }
      if (maxPs == null) {
        continue; // No patch sets matched.
      }
      ObjectId id = ObjectId.fromString(maxPs.getRevision().get());
      try {
        RevCommit c = rw.parseCommit(id);
        byCommit.put(c, PatchSetData.create(cd, maxPs, c));
      } catch (MissingObjectException | IncorrectObjectTypeException e) {
        log.warn("missing commit " + id.name() + " for patch set " + maxPs.getId(), e);
      }
    }
    return byCommit;
  }

  private boolean shouldInclude(PatchSet ps) {
    return includePatchSets.isEmpty() || includePatchSets.contains(ps.getId());
  }

  private static void markStart(RevWalk rw, Iterable<RevCommit> commits) throws IOException {
    for (RevCommit c : commits) {
      rw.markStart(c);
    }
  }

  @AutoValue
  public abstract static class PatchSetData {
    @VisibleForTesting
    static PatchSetData create(ChangeData cd, PatchSet ps, RevCommit commit) {
      return new AutoValue_WalkSorter_PatchSetData(cd, ps, commit);
    }

    public abstract ChangeData data();

    abstract PatchSet patchSet();

    abstract RevCommit commit();
  }
}
