// Copyright (C) 2014 Google Inc. All Rights Reserved.
//
// 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.gitiles.blame.cache;

import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.hash;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import org.eclipse.jgit.blame.BlameGenerator;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.eclipse.jgit.util.QuotedString;

/** Guava implementation of BlameCache, weighted by number of blame regions. */
public class BlameCacheImpl implements BlameCache {
  public static CacheBuilder<Key, List<Region>> defaultBuilder() {
    return weigher(CacheBuilder.newBuilder()).maximumWeight(10 << 10);
  }

  public static CacheBuilder<Key, List<Region>> weigher(
      CacheBuilder<? super Key, ? super List<Region>> builder) {
    return builder.weigher((k, v) -> v.size());
  }

  public static class Key {
    private final ObjectId commitId;
    private final String path;

    public Key(ObjectId commitId, String path) {
      this.commitId = commitId;
      this.path = path;
    }

    public ObjectId getCommitId() {
      return commitId;
    }

    public String getPath() {
      return path;
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof Key) {
        Key k = (Key) o;
        return Objects.equals(commitId, k.commitId) && Objects.equals(path, k.path);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return hash(commitId, path);
    }

    @Override
    public String toString() {
      return commitId.name() + ":" + QuotedString.GIT_PATH.quote(path);
    }
  }

  private final Cache<Key, List<Region>> cache;

  public BlameCacheImpl() {
    this(defaultBuilder());
  }

  public Cache<Key, List<Region>> getCache() {
    return cache;
  }

  public Callable<List<Region>> newLoader(Key key, Repository repo) {
    return () -> loadBlame(key, repo);
  }

  public BlameCacheImpl(CacheBuilder<? super Key, ? super List<Region>> builder) {
    this.cache = builder.build();
  }

  @Override
  public List<Region> get(Repository repo, ObjectId commitId, String path) throws IOException {
    try {
      Key key = new Key(commitId, path);
      return cache.get(key, newLoader(key, repo));
    } catch (ExecutionException e) {
      throw new IOException(e);
    }
  }

  @Override
  public ObjectId findLastCommit(Repository repo, ObjectId commitId, String path)
      throws IOException {
    // Default implementation does no caching.
    try (RevWalk rw = new RevWalk(repo)) {
      rw.markStart(rw.parseCommit(commitId));
      rw.setRewriteParents(false);
      // Don't use rename detection, even though BlameGenerator does. It is not
      // possible for a commit to modify a path when not doing rename detection
      // but to not modify the same path when taking renames into account.
      rw.setTreeFilter(
          AndTreeFilter.create(PathFilterGroup.createFromStrings(path), TreeFilter.ANY_DIFF));
      return rw.next();
    }
  }

  public static List<Region> loadBlame(Key key, AnyObjectId blameCommit, Repository repo)
      throws IOException {
    if (blameCommit == null) {
      return loadBlame(key, repo);
    }

    try (BlameGenerator gen = new BlameGenerator(repo, key.path)) {
      gen.push(null, blameCommit);
      if (gen.getResultContents() == null) {
        return ImmutableList.of();
      }
      return loadRegions(gen);
    }
  }

  public static List<Region> loadBlame(Key key, Repository repo) throws IOException {
    return loadBlame(key, key.commitId, repo);
  }

  private static class PooledCommit {
    final ObjectId commit;
    final PersonIdent author;

    private PooledCommit(ObjectId commit, PersonIdent author) {
      this.commit = commit;
      this.author = author;
    }
  }

  private static List<Region> loadRegions(BlameGenerator gen) throws IOException {
    Map<ObjectId, PooledCommit> commits = Maps.newHashMap();
    Interner<String> strings = Interners.newStrongInterner();
    int lineCount = gen.getResultContents().size();

    List<Region> regions = Lists.newArrayList();
    while (gen.next()) {
      String path = gen.getSourcePath();
      PersonIdent author = gen.getSourceAuthor();
      ObjectId commit = gen.getSourceCommit();
      checkState(path != null && author != null && commit != null);

      PooledCommit pc = commits.get(commit);
      if (pc == null) {
        pc =
            new PooledCommit(
                commit.copy(),
                new PersonIdent(
                    strings.intern(author.getName()),
                    strings.intern(author.getEmailAddress()),
                    author.getWhen(),
                    author.getTimeZone()));
        commits.put(pc.commit, pc);
      }
      path = strings.intern(path);
      commit = pc.commit;
      author = pc.author;
      regions.add(new Region(path, commit, author, gen.getResultStart(), gen.getResultEnd()));
    }
    Collections.sort(regions);

    // Fill in any gaps left by bugs in JGit, since rendering code assumes the
    // full set of contiguous regions.
    List<Region> result = Lists.newArrayListWithExpectedSize(regions.size());
    Region last = null;
    for (Region r : regions) {
      if (last != null) {
        checkState(last.getEnd() <= r.getStart());
        if (last.getEnd() < r.getStart()) {
          result.add(
              new Region(null, null, null, /* start= */ last.getEnd(), /* end= */ r.getStart()));
        }
      }
      result.add(r);
      last = r;
    }
    if (last != null && last.getEnd() != lineCount) {
      result.add(new Region(null, null, null, last.getEnd(), lineCount));
    }

    return ImmutableList.copyOf(result);
  }
}
