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