// Copyright (C) 2017 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.findowners;


import com.google.common.cache.CacheBuilder;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.Emails;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.ChangeData;
import java.time.Duration;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

/** Save OwnersDb in a cache for multiple calls to submit_filter. */
class Cache {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  // The OwnersDb is created from OWNERS files in directories that
  // contain changed files of a patch set, which belongs to a project
  // and branch. OwnersDb can be cached if the head of a project branch
  // and the patch set are not changed.

  // Although the head of a project branch could be changed by other users,
  // it is better to assume the same for a patch set during a short period
  // of time. So multiple checks would have the same result. For example,
  // one client UI action can trigger multiple HTTP requests.
  // Each HTTP request has one StoredValues,
  // and can trigger multiple Prolog submit_filter.
  // Each submit_filter has one Prolog engine.
  // It would not be enough to keep the cache in a Prolog engine environment
  // or a StoredValues.

  // Since a Java runtime can host multiple Gerrit sites, each site should have
  // its own cache. We assume that each site has its own GitRepositoryManager.
  // We use a WeakHashMap to avoid leaking objects in the map.
  private static final Map<GitRepositoryManager, Cache> cacheMap =
      Collections.synchronizedMap(new WeakHashMap<GitRepositoryManager, Cache>());

  // dbCache key is generated by makeKey.
  private com.google.common.cache.Cache<String, OwnersDb> dbCache;

  private Config config; // global config shared by all OwnersDb in dbCache

  private Cache(Config config) {
    this.config = config;
    init(config.getMaxCacheAge(), config.getMaxCacheSize());
  }

  long size() {
    return (dbCache == null) ? 0 : dbCache.size();
  }

  Cache init(int maxSeconds, int maxSize) {
    // This should be called once in normal configuration,
    // but could be called multiple times in unit or integration tests.
    if (dbCache != null) {
      dbCache.invalidateAll(); // release all cached objects
    }
    if (maxSeconds > 0) {
      logger.atInfo().log("Initialize Cache with maxSeconds=%d maxSize=%d", maxSeconds, maxSize);
      dbCache =
          CacheBuilder.newBuilder()
              .maximumSize(maxSize)
              .expireAfterWrite(Duration.ofSeconds(maxSeconds))
              .build();
    } else {
      logger.atInfo().log("Cache disabled.");
      dbCache = null;
    }
    return this;
  }

  /** Returns a cached or new OwnersDb, for the current patchset. */
  OwnersDb get(
      Boolean useCache,
      PermissionBackend permissionBackend,
      ProjectState projectState,
      AccountCache accountCache,
      Emails emails,
      GitRepositoryManager repoManager,
      ChangeData changeData)
      throws StorageException {
    return get(
        useCache,
        permissionBackend,
        projectState,
        accountCache,
        emails,
        repoManager,
        changeData,
        changeData.currentPatchSet().id().get());
  }

  /** Returns a cached or new OwnersDb, for the specified patchset. */
  OwnersDb get(
      Boolean useCache,
      PermissionBackend permissionBackend,
      ProjectState projectState,
      AccountCache accountCache,
      Emails emails,
      GitRepositoryManager repoManager,
      ChangeData changeData,
      int patchset)
      throws StorageException {
    String branch = changeData.change().getDest().branch();
    String dbKey = Cache.makeKey(changeData.getId().get(), patchset, repoManager);
    // TODO: get changed files of the given patchset?
    return get(
        useCache,
        permissionBackend,
        projectState,
        accountCache,
        emails,
        dbKey,
        repoManager,
        changeData,
        branch,
        changeData.currentFilePaths());
  }

  /** Returns a cached or new OwnersDb, for the specified branch and changed files. */
  OwnersDb get(
      Boolean useCache,
      PermissionBackend permissionBackend,
      ProjectState projectState,
      AccountCache accountCache,
      Emails emails,
      String key,
      GitRepositoryManager repoManager,
      ChangeData changeData,
      String branch,
      Collection<String> files) {
    if (dbCache == null || !useCache) { // Do not cache OwnersDb
      logger.atFiner().log("Create new OwnersDb, key=%s", key);
      return new OwnersDb(
          permissionBackend,
          projectState,
          accountCache,
          emails,
          key,
          repoManager,
          config,
          changeData,
          branch,
          files);
    }
    try {
      logger.atFiner().log(
          "Get from cache %s, key=%s, cache size=%d", dbCache, key, dbCache.size());
      return dbCache.get(
          key,
          new Callable<OwnersDb>() {
            @Override
            public OwnersDb call() {
              logger.atFiner().log("Create new OwnersDb, key=%s", key);
              return new OwnersDb(
                  permissionBackend,
                  projectState,
                  accountCache,
                  emails,
                  key,
                  repoManager,
                  config,
                  changeData,
                  branch,
                  files);
            }
          });
    } catch (ExecutionException e) {
      logger.atSevere().withCause(e).log(
          "Cache.get has exception for %s", Config.getChangeId(changeData));
      return new OwnersDb(
          permissionBackend,
          projectState,
          accountCache,
          emails,
          key,
          repoManager,
          config,
          changeData,
          branch,
          files);
    }
  }

  public static String makeKey(int change, int patch, GitRepositoryManager repoManager) {
    return String.format("%d:%d:%H", change, patch, repoManager);
  }

  public static Cache getInstance(Config config, GitRepositoryManager repoManager) {
    Cache cache = cacheMap.get(repoManager);
    if (cache == null) {
      cache = new Cache(config);
      cacheMap.put(repoManager, cache);
    }
    cache.config = config; // Always use newest config, although dbCache could have older data.
    return cache;
  }
}
