// Copyright (C) 2021 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.google.gerrit.plugins.codeowners.backend;

import com.google.auto.value.AutoValue;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.HashMap;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;

/**
 * Class to load and cache {@link CodeOwnerConfig}s within a request.
 *
 * <p>This cache is transient, which means the code owner configs stay cached only for the lifetime
 * of the {@code TransientCodeOwnerConfigCache} instance.
 *
 * <p><strong>Note</strong>: This class is not thread-safe.
 */
public class TransientCodeOwnerConfigCache implements CodeOwnerConfigLoader {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final GitRepositoryManager repoManager;
  private final CodeOwners codeOwners;
  private final Optional<Integer> maxCacheSize;
  private final Counters counters;
  private final HashMap<CacheKey, Optional<CodeOwnerConfig>> cache = new HashMap<>();

  @Inject
  TransientCodeOwnerConfigCache(
      CodeOwnersPluginConfiguration codeOwnersPluginConfiguration,
      GitRepositoryManager repoManager,
      CodeOwners codeOwners,
      CodeOwnerMetrics codeOwnerMetrics) {
    this.repoManager = repoManager;
    this.codeOwners = codeOwners;
    this.maxCacheSize = codeOwnersPluginConfiguration.getMaxCodeOwnerConfigCacheSize();
    this.counters = new Counters(codeOwnerMetrics);
  }

  /**
   * Gets the specified code owner config from the cache, if it was previously retrieved. Otherwise
   * loads and returns the code owner config.
   */
  @Override
  public Optional<CodeOwnerConfig> get(
      CodeOwnerConfig.Key codeOwnerConfigKey, @Nullable ObjectId revision) {
    CacheKey cacheKey = CacheKey.create(codeOwnerConfigKey, revision);
    Optional<CodeOwnerConfig> cachedCodeOwnerConfig = cache.get(cacheKey);
    if (cachedCodeOwnerConfig != null) {
      counters.incrementCacheReads();
      return cachedCodeOwnerConfig;
    }
    return loadAndCache(cacheKey);
  }

  /**
   * Gets the specified code owner config from the cache, if it was previously retrieved. Otherwise
   * loads and returns the code owner config.
   */
  @Override
  public Optional<CodeOwnerConfig> getFromCurrentRevision(CodeOwnerConfig.Key codeOwnerConfigKey) {
    return get(codeOwnerConfigKey, /* revision= */ null);
  }

  /** Load a code owner config and puts it into the cache. */
  private Optional<CodeOwnerConfig> loadAndCache(CacheKey cacheKey) {
    counters.incrementBackendReads();
    Optional<CodeOwnerConfig> codeOwnerConfig;
    if (cacheKey.revision().isPresent()) {
      codeOwnerConfig = codeOwners.get(cacheKey.codeOwnerConfigKey(), cacheKey.revision().get());
    } else {
      Optional<ObjectId> revision = getRevision(cacheKey.codeOwnerConfigKey().branchNameKey());
      if (revision.isPresent()) {
        codeOwnerConfig = codeOwners.get(cacheKey.codeOwnerConfigKey(), revision.get());
      } else {
        // branch does not exists, hence the code owner config also doesn't exist
        codeOwnerConfig = Optional.empty();
      }
    }
    if (!maxCacheSize.isPresent() || cache.size() < maxCacheSize.get()) {
      cache.put(cacheKey, codeOwnerConfig);
    } else if (maxCacheSize.isPresent()) {
      logger.atWarning().atMostEvery(1, TimeUnit.DAYS).log(
          "exceeded limit of %s (project = %s)",
          getClass().getSimpleName(), cacheKey.codeOwnerConfigKey().project());
    }
    return codeOwnerConfig;
  }

  /**
   * Gets the revision for the given branch.
   *
   * <p>Returns {@link Optional#empty()} if the branch doesn't exist.
   */
  private Optional<ObjectId> getRevision(BranchNameKey branchNameKey) {
    try (Repository repo = repoManager.openRepository(branchNameKey.project())) {
      Ref ref = repo.exactRef(branchNameKey.branch());
      if (ref == null) {
        // branch does not exist
        return Optional.empty();
      }
      return Optional.of(ref.getObjectId());
    } catch (IOException e) {
      throw new CodeOwnersInternalServerErrorException(
          String.format(
              "failed to get revision of branch %s in project %s",
              branchNameKey.shortName(), branchNameKey.project()),
          e);
    }
  }

  @AutoValue
  abstract static class CacheKey {
    /** The key of the code owner config. */
    public abstract CodeOwnerConfig.Key codeOwnerConfigKey();

    /** The revision from which the code owner config was loaded. */
    public abstract Optional<ObjectId> revision();

    public static CacheKey create(
        CodeOwnerConfig.Key codeOwnerConfigKey, @Nullable ObjectId revision) {
      return new AutoValue_TransientCodeOwnerConfigCache_CacheKey(
          codeOwnerConfigKey, Optional.ofNullable(revision));
    }
  }

  public Counters getCounters() {
    return counters;
  }

  public static class Counters {
    private final CodeOwnerMetrics codeOwnerMetrics;

    private int cacheReadCount;
    private int backendReadCount;

    private Counters(CodeOwnerMetrics codeOwnerMetrics) {
      this.codeOwnerMetrics = codeOwnerMetrics;
    }

    private void incrementCacheReads() {
      codeOwnerMetrics.countCodeOwnerConfigCacheReads.increment();
      cacheReadCount++;
    }

    private void incrementBackendReads() {
      // we do not increase the countCodeOwnerConfigReads metric here, since this is already done in
      // CodeOwners
      backendReadCount++;
    }

    public int getBackendReadCount() {
      return backendReadCount;
    }

    public int getCacheReadCount() {
      return cacheReadCount;
    }
  }
}
