// 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.common.flogger.FluentLogger;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
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.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevFlag;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * 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 FluentLogger logger = FluentLogger.forEnclosingClass();

  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 (StorageException 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 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()));
    }
    sortedByProject.sort(PROJECT_LIST_SORTER);
    return Iterables.concat(sortedByProject);
  }

  private ImmutableList<PatchSetData> sortProject(
      Project.NameKey project, Collection<ChangeData> in) throws 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 ImmutableList.copyOf(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 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.id().get() > maxPs.id().get())) {
          maxPs = ps;
        }
      }
      if (maxPs == null) {
        continue; // No patch sets matched.
      }
      try {
        RevCommit c = rw.parseCommit(maxPs.commitId());
        byCommit.put(c, PatchSetData.create(cd, maxPs, c));
      } catch (MissingObjectException | IncorrectObjectTypeException e) {
        logger.atWarning().withCause(e).log(
            "missing commit %s for patch set %s", maxPs.commitId().name(), maxPs.id());
      }
    }
    return byCommit;
  }

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

  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();
  }
}
