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

import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Objects.hash;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Throwables;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Streams;
import com.google.common.util.concurrent.ExecutionError;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

/** Cache of per-user object visibility. */
public class VisibilityCache {

  private static class Key {
    private final Object user;
    private final String repositoryName;
    private final ObjectId objectId;

    private Key(Object user, String repositoryName, ObjectId objectId) {
      this.user = checkNotNull(user, "user");
      this.repositoryName = checkNotNull(repositoryName, "repositoryName");
      this.objectId = checkNotNull(objectId, "objectId").copy();
    }

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

    @Override
    public int hashCode() {
      return hash(user, repositoryName, objectId);
    }

    @Override
    public String toString() {
      return toStringHelper(this)
          .add("user", user)
          .add("repositoryName", repositoryName)
          .add("objectId", objectId)
          .toString();
    }
  }

  private final Cache<Key, Boolean> cache;
  private final VisibilityChecker checker;

  public static CacheBuilder<Object, Object> defaultBuilder() {
    return CacheBuilder.newBuilder().maximumSize(1 << 10).expireAfterWrite(30, TimeUnit.MINUTES);
  }

  public VisibilityCache() {
    this(new VisibilityChecker(), defaultBuilder());
  }

  public VisibilityCache(CacheBuilder<Object, Object> builder) {
    this(new VisibilityChecker(), builder);
  }

  /**
   * Use the constructors with a boolean parameter (e.g. {@link #VisibilityCache()}). The default
   * visibility checker should cover all common use cases.
   *
   * <p>This constructor is useful to use a checker with additional logging or metrics collection,
   * for example.
   */
  public VisibilityCache(VisibilityChecker checker) {
    this(checker, defaultBuilder());
  }

  /**
   * Use the constructors with a boolean parameter (e.g. {@link #VisibilityCache()}). The default
   * visibility checker should cover all common use cases.
   *
   * <p>This constructor is useful to use a checker with additional logging or metrics collection,
   * for example.
   */
  public VisibilityCache(VisibilityChecker checker, CacheBuilder<Object, Object> builder) {
    this.cache = builder.build();
    this.checker = checker;
  }

  public Cache<?, Boolean> getCache() {
    return cache;
  }

  @VisibleForTesting
  boolean isVisible(
      final Repository repo,
      final RevWalk walk,
      GitilesAccess access,
      final ObjectId id,
      final ObjectId... knownReachable)
      throws IOException {
    try {
      return cache.get(
          new Key(access.getUserKey(), access.getRepositoryName(), id),
          () -> isVisible(repo, walk, id, Arrays.asList(knownReachable)));
    } catch (ExecutionException e) {
      Throwables.throwIfInstanceOf(e.getCause(), IOException.class);
      throw new IOException(e);
    } catch (ExecutionError e) {
      // markUninteresting may overflow on pathological repos with very long merge chains. Play it
      // safe and return false rather than letting the error propagate.
      if (e.getCause() instanceof StackOverflowError) {
        return false;
      }
      throw e;
    }
  }

  boolean isVisible(Repository repo, RevWalk walk, ObjectId id, Collection<ObjectId> knownReachable)
      throws IOException {
    RevCommit commit;
    try {
      commit = walk.parseCommit(id);
    } catch (IncorrectObjectTypeException e) {
      return false;
    }

    RefDatabase refDb = repo.getRefDatabase();
    if (checker.isTipOfBranch(refDb, id)) {
      return true;
    }

    Stream<ObjectId> reachableTips =
        importantRefsFirst(refDb.getRefsByPrefix(RefDatabase.ALL))
            .map(VisibilityCache::refToObjectId);

    // Check heads first under the assumption that most requests are for refs close to a head. Tags
    // tend to be much further back in history and just clutter up the priority queue in the common
    // case.
    Stream<RevCommit> startCommits =
        Stream.concat(knownReachable.stream(), reachableTips)
            .map(objId -> VisibilityChecker.objectIdToRevCommit(walk, objId))
            .filter(Objects::nonNull); // Ignore missing tips

    return checker.isReachableFrom(walk, commit, startCommits);
  }

  static Stream<Ref> importantRefsFirst(Collection<Ref> visibleRefs) {
    Predicate<Ref> startsWithRefsHeads = ref -> ref.getName().startsWith(Constants.R_HEADS);
    Predicate<Ref> startsWithRefsTags = ref -> ref.getName().startsWith(Constants.R_TAGS);
    Predicate<Ref> startsWithRefsChanges = ref -> ref.getName().startsWith("refs/changes");
    Predicate<Ref> allOther =
        ref ->
            !startsWithRefsHeads.test(ref)
                && !startsWithRefsTags.test(ref)
                && !startsWithRefsChanges.test(ref);

    return Streams.concat(
        visibleRefs.stream().filter(startsWithRefsHeads),
        visibleRefs.stream().filter(startsWithRefsTags),
        visibleRefs.stream().filter(allOther));
  }

  private static ObjectId refToObjectId(Ref ref) {
    return ref.getObjectId() != null ? ref.getObjectId() : ref.getPeeledObjectId();
  }
}
