// Copyright (C) 2018 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 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.server.cache.serialize.CacheSerializer;
import com.google.gerrit.server.cache.serialize.JavaCacheSerializer;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import java.io.Serializable;
import java.time.Duration;

class PersistentCacheProvider<K, V> extends CacheProvider<K, V>
    implements Provider<Cache<K, V>>, PersistentCacheBinding<K, V>, PersistentCacheDef<K, V> {
  private final CacheBackend backend;
  private int version;
  private long diskLimit;
  private CacheSerializer<K> keySerializer;
  private CacheSerializer<V> valueSerializer;

  private PersistentCacheFactory persistentCacheFactory;

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

  PersistentCacheProvider(
      CacheModule module,
      String name,
      TypeLiteral<K> keyType,
      TypeLiteral<V> valType,
      CacheBackend backend) {
    super(module, name, keyType, valType, backend);
    version = -1;
    diskLimit = 128 << 20;
    this.backend = backend;
  }

  @Inject(optional = true)
  void setPersistentCacheFactory(@Nullable PersistentCacheFactory factory) {
    this.persistentCacheFactory = factory;
  }

  @Override
  public PersistentCacheBinding<K, V> maximumWeight(long weight) {
    return (PersistentCacheBinding<K, V>) super.maximumWeight(weight);
  }

  @Override
  public PersistentCacheBinding<K, V> expireAfterWrite(Duration duration) {
    return (PersistentCacheBinding<K, V>) super.expireAfterWrite(duration);
  }

  @Override
  public PersistentCacheBinding<K, V> loader(Class<? extends CacheLoader<K, V>> clazz) {
    return (PersistentCacheBinding<K, V>) super.loader(clazz);
  }

  @Override
  public PersistentCacheBinding<K, V> expireFromMemoryAfterAccess(Duration duration) {
    return (PersistentCacheBinding<K, V>) super.expireFromMemoryAfterAccess(duration);
  }

  @Override
  public PersistentCacheBinding<K, V> weigher(Class<? extends Weigher<K, V>> clazz) {
    return (PersistentCacheBinding<K, V>) super.weigher(clazz);
  }

  @Override
  public PersistentCacheBinding<K, V> version(int version) {
    this.version = version;
    return this;
  }

  @Override
  public PersistentCacheBinding<K, V> keySerializer(CacheSerializer<K> keySerializer) {
    this.keySerializer = keySerializer;
    return this;
  }

  @Override
  public PersistentCacheBinding<K, V> valueSerializer(CacheSerializer<V> valueSerializer) {
    this.valueSerializer = valueSerializer;
    return this;
  }

  @Override
  public PersistentCacheBinding<K, V> diskLimit(long limit) {
    checkNotFrozen();
    diskLimit = limit;
    return this;
  }

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

  @Override
  public int version() {
    return version;
  }

  @Override
  public CacheSerializer<K> keySerializer() {
    return keySerializer;
  }

  @Override
  public CacheSerializer<V> valueSerializer() {
    return valueSerializer;
  }

  @Override
  public Cache<K, V> get() {
    if (persistentCacheFactory == null) {
      return super.get();
    }
    checkState(version >= 0, "version is required");
    checkSerializer(keyType(), keySerializer, "key");
    checkSerializer(valueType(), valueSerializer, "value");
    freeze();
    CacheLoader<K, V> ldr = loader();
    return ldr != null
        ? persistentCacheFactory.build(this, ldr, backend)
        : persistentCacheFactory.build(this, backend);
  }

  private static <T> void checkSerializer(
      TypeLiteral<T> type, CacheSerializer<T> serializer, String name) {
    checkState(serializer != null, "%sSerializer is required", name);
    if (serializer instanceof JavaCacheSerializer) {
      checkState(
          Serializable.class.isAssignableFrom(type.getRawType()),
          "%s type %s must implement Serializable",
          name,
          type);
    }
  }
}
