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

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.cache.Weigher;
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 org.eclipse.jgit.blame.BlameGenerator;
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;

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;

/** 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(
        new Weigher<Key, List<Region>>() {
          @Override
          public int weigh(Key key, List<Region> value) {
            return value.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(final Key key, final Repository repo) {
    return new Callable<List<Region>>() {
      @Override
      public List<Region> call() throws IOException {
        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, Repository repo) throws IOException {
    try (BlameGenerator gen = new BlameGenerator(repo, key.path)) {
      gen.push(null, key.commitId);
      return loadRegions(gen);
    }
  }

  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, last.getEnd(), 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);
  }
}
