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

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.TreeFilter;

public class CommitUtils {

  /**
   * This method spots all files which differ between the passed commit and its parents. The paths
   * of the spotted files will be returned as a Set.
   *
   * @param repo The repository
   * @param c The commit
   * @return A Set containing the paths of all files which differ between the passed commit and its
   *     parents.
   * @throws IOException
   */
  public static Set<String> getChangedPaths(Repository repo, RevCommit c) throws IOException {
    Map<String, ObjectId> content = getChangedContent(repo, c);
    return content.keySet();
  }

  /**
   * This method spots all files which differ between the passed commit and its parents. The spotted
   * files will be returned as a Map. The structure of the returned map looks like this:
   *
   * <p>
   *
   * <ul>
   *   <li>Key: Path to the changed file.
   *   <li>Value: ObjectId of the changed file.
   * </ul>
   *
   * @param repo The repository
   * @param c The commit
   * @return A Map containing all files which differ between the passed commit and its parents.
   * @throws IOException
   */
  public static Map<String, ObjectId> getChangedContent(Repository repo, RevCommit c)
      throws IOException {
    final Map<String, ObjectId> content = new HashMap<>();

    visitChangedEntries(
        repo,
        c,
        new TreeWalkVisitor() {
          @Override
          public void onVisit(TreeWalk tw) {
            if (isFile(tw)) {
              content.put(tw.getPathString(), tw.getObjectId(0));
            }
          }
        });
    return content;
  }

  private static boolean isFile(TreeWalk tw) {
    return FileMode.EXECUTABLE_FILE.equals(tw.getRawMode(0))
        || FileMode.REGULAR_FILE.equals(tw.getRawMode(0));
  }

  /**
   * This method spots all TreeWalk entries which differ between the passed commit and its parents.
   * If a TreeWalk entry is found this method calls the onVisit() method of the class
   * TreeWalkVisitor.
   *
   * @param repo The repository
   * @param c The commit
   * @param visitor A TreeWalkVisitor with the desired action
   * @throws IOException
   */
  public static void visitChangedEntries(Repository repo, RevCommit c, TreeWalkVisitor visitor)
      throws IOException {
    try (TreeWalk tw = new TreeWalk(repo)) {
      tw.setRecursive(true);
      tw.setFilter(TreeFilter.ANY_DIFF);
      tw.addTree(c.getTree());
      if (c.getParentCount() > 0) {
        @SuppressWarnings("resource")
        RevWalk rw = null;
        try {
          for (RevCommit p : c.getParents()) {
            if (p.getTree() == null) {
              if (rw == null) {
                rw = new RevWalk(repo);
              }
              rw.parseHeaders(p);
            }
            tw.addTree(p.getTree());
          }
        } finally {
          if (rw != null) {
            rw.close();
          }
        }
        while (tw.next()) {
          if (isDifferentToAllParents(c, tw)) {
            visitor.onVisit(tw);
          }
        }
      } else {
        while (tw.next()) {
          visitor.onVisit(tw);
        }
      }
    }
  }

  private static boolean isDifferentToAllParents(RevCommit c, TreeWalk tw) {
    if (c.getParentCount() > 1) {
      for (int p = 1; p <= c.getParentCount(); p++) {
        if (tw.getObjectId(0).equals(tw.getObjectId(p))) {
          return false;
        }
      }
    }
    return true;
  }
}
