// Copyright (C) 2012 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.server.cache;

import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;

import com.google.common.base.Strings;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.Weigher;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import java.time.Duration;

class CacheProvider<K, V> implements Provider<Cache<K, V>>, CacheBinding<K, V>, CacheDef<K, V> {
  private final CacheModule module;
  private final CacheBackend backend;
  final String name;
  private final TypeLiteral<K> keyType;
  private final TypeLiteral<V> valType;
  private String configKey;
  private long maximumWeight;
  private Duration expireAfterWrite;
  private Duration expireFromMemoryAfterAccess;
  private Duration refreshAfterWrite;
  private Provider<CacheLoader<K, V>> loader;
  private Provider<Weigher<K, V>> weigher;

  private String plugin;
  private MemoryCacheFactory memoryCacheFactory;
  private boolean frozen;

  CacheProvider(
      CacheModule module,
      String name,
      TypeLiteral<K> keyType,
      TypeLiteral<V> valType,
      CacheBackend backend) {
    this.module = module;
    this.name = name;
    this.keyType = keyType;
    this.valType = valType;
    this.backend = backend;
  }

  @Inject(optional = true)
  void setPluginName(@PluginName String pluginName) {
    this.plugin = pluginName;
  }

  @Inject
  void setMemoryCacheFactory(MemoryCacheFactory factory) {
    this.memoryCacheFactory = factory;
  }

  @Override
  public CacheBinding<K, V> maximumWeight(long weight) {
    checkNotFrozen();
    maximumWeight = weight;
    return this;
  }

  @Override
  public CacheBinding<K, V> expireAfterWrite(Duration duration) {
    checkNotFrozen();
    expireAfterWrite = duration;
    return this;
  }

  @Override
  public CacheBinding<K, V> expireFromMemoryAfterAccess(Duration duration) {
    checkNotFrozen();
    expireFromMemoryAfterAccess = duration;
    return this;
  }

  @Override
  public CacheBinding<K, V> refreshAfterWrite(Duration duration) {
    checkNotFrozen();
    refreshAfterWrite = duration;
    return this;
  }

  @Override
  public CacheBinding<K, V> loader(Class<? extends CacheLoader<K, V>> impl) {
    checkNotFrozen();
    loader = module.bindCacheLoader(this, impl);
    return this;
  }

  @Override
  public CacheBinding<K, V> weigher(Class<? extends Weigher<K, V>> impl) {
    checkNotFrozen();
    weigher = module.bindWeigher(this, impl);
    return this;
  }

  @Override
  public CacheBinding<K, V> configKey(String name) {
    checkNotFrozen();
    configKey = requireNonNull(name);
    return this;
  }

  @Override
  public String name() {
    if (!Strings.isNullOrEmpty(plugin)) {
      return plugin + "." + name;
    }
    return name;
  }

  @Override
  public String configKey() {
    return configKey != null ? configKey : name();
  }

  @Override
  public TypeLiteral<K> keyType() {
    return keyType;
  }

  @Override
  public TypeLiteral<V> valueType() {
    return valType;
  }

  @Override
  public long maximumWeight() {
    return maximumWeight;
  }

  @Override
  @Nullable
  public Duration expireAfterWrite() {
    return expireAfterWrite;
  }

  @Override
  @Nullable
  public Duration expireFromMemoryAfterAccess() {
    return expireFromMemoryAfterAccess;
  }

  @Override
  public Duration refreshAfterWrite() {
    return refreshAfterWrite;
  }

  @Override
  @Nullable
  public Weigher<K, V> weigher() {
    return weigher != null ? weigher.get() : null;
  }

  @Override
  @Nullable
  public CacheLoader<K, V> loader() {
    return loader != null ? loader.get() : null;
  }

  @Override
  public Cache<K, V> get() {
    freeze();
    CacheLoader<K, V> ldr = loader();
    return ldr != null
        ? memoryCacheFactory.build(this, ldr, backend)
        : memoryCacheFactory.build(this, backend);
  }

  protected void checkNotFrozen() {
    checkState(!frozen, "binding frozen, cannot be modified");
  }

  protected void freeze() {
    frozen = true;
  }
}
