// Copyright (C) 2009 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 java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;

import com.google.gerrit.lifecycle.LifecycleListener;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;

import net.sf.ehcache.CacheManager;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.DiskStoreConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;

import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

/** Pool of all declared caches created by {@link CacheModule}s. */
@Singleton
public class CachePool {
  private static final Logger log = LoggerFactory.getLogger(CachePool.class);

  public static class Lifecycle implements LifecycleListener {
    private final CachePool cachePool;

    @Inject
    Lifecycle(final CachePool cachePool) {
      this.cachePool = cachePool;
    }

    @Override
    public void start() {
      cachePool.start();
    }

    @Override
    public void stop() {
      cachePool.stop();
    }
  }

  private final Config config;
  private final SitePaths site;

  private final Object lock = new Object();
  private final Map<String, CacheProvider<?, ?>> caches;
  private CacheManager manager;

  @Inject
  CachePool(@GerritServerConfig final Config cfg, final SitePaths site) {
    this.config = cfg;
    this.site = site;
    this.caches = new HashMap<String, CacheProvider<?, ?>>();
  }

  private void start() {
    synchronized (lock) {
      if (manager != null) {
        throw new IllegalStateException("Cache pool has already been started");
      }

      try {
        System.setProperty("net.sf.ehcache.skipUpdateCheck", "" + true);
      } catch (SecurityException e) {
        // Ignore it, the system is just going to ping some external page
        // using a background thread and there's not much we can do about
        // it now.
      }

      manager = new CacheManager(new Factory().toConfiguration());
      for (CacheProvider<?, ?> p : caches.values()) {
        p.bind(manager.getEhcache(p.getName()));
      }
    }
  }

  private void stop() {
    synchronized (lock) {
      if (manager != null) {
        manager.shutdown();
      }
    }
  }

  /** <i>Discouraged</i> Get the underlying cache descriptions, for statistics. */
  public CacheManager getCacheManager() {
    synchronized (lock) {
      return manager;
    }
  }

  <K, V> ProxyEhcache register(final CacheProvider<K, V> provider) {
    synchronized (lock) {
      if (manager != null) {
        throw new IllegalStateException("Cache pool has already been started");
      }

      final String n = provider.getName();
      if (caches.containsKey(n) && caches.get(n) != provider) {
        throw new IllegalStateException("Cache \"" + n + "\" already defined");
      }
      caches.put(n, provider);
      return new ProxyEhcache(n);
    }
  }

  private class Factory {
    private static final int MB = 1024 * 1024;
    private final Configuration mgr = new Configuration();

    Configuration toConfiguration() {
      configureDiskStore();
      configureDefaultCache();

      for (CacheProvider<?, ?> p : caches.values()) {
        final String name = p.getName();
        final CacheConfiguration c = newCache(name);
        c.setMemoryStoreEvictionPolicyFromObject(toPolicy(p.evictionPolicy()));

        c.setMaxElementsInMemory(getInt(name, "memorylimit", p.memoryLimit()));

        c.setTimeToIdleSeconds(0);
        c.setTimeToLiveSeconds(getSeconds(name, "maxage", p.maxAge()));
        c.setEternal(c.getTimeToLiveSeconds() == 0);

        if (p.disk() && mgr.getDiskStoreConfiguration() != null) {
          c.setMaxElementsOnDisk(getInt(name, "disklimit", p.diskLimit()));

          int v = c.getDiskSpoolBufferSizeMB() * MB;
          v = getInt(name, "diskbuffer", v) / MB;
          c.setDiskSpoolBufferSizeMB(Math.max(1, v));
          c.setOverflowToDisk(c.getMaxElementsOnDisk() > 0);
          c.setDiskPersistent(c.getMaxElementsOnDisk() > 0);
        }

        mgr.addCache(c);
      }

      return mgr;
    }

    private MemoryStoreEvictionPolicy toPolicy(final EvictionPolicy policy) {
      switch (policy) {
        case LFU:
          return MemoryStoreEvictionPolicy.LFU;

        case LRU:
          return MemoryStoreEvictionPolicy.LRU;

        default:
          throw new IllegalArgumentException("Unsupported " + policy);
      }
    }

    private int getInt(String n, String s, int d) {
      return config.getInt("cache", n, s, d);
    }

    private long getSeconds(String n, String s, long d) {
      d = MINUTES.convert(d, SECONDS);
      long m = ConfigUtil.getTimeUnit(config, "cache", n, s, d, MINUTES);
      return SECONDS.convert(m, MINUTES);
    }

    private void configureDiskStore() {
      boolean needDisk = false;
      for (CacheProvider<?, ?> p : caches.values()) {
        if (p.disk()) {
          needDisk = true;
          break;
        }
      }
      if (!needDisk) {
        return;
      }

      File loc = site.resolve(config.getString("cache", null, "directory"));
      if (loc == null) {
      } else if (loc.exists() || loc.mkdirs()) {
        if (loc.canWrite()) {
          final DiskStoreConfiguration c = new DiskStoreConfiguration();
          c.setPath(loc.getAbsolutePath());
          mgr.addDiskStore(c);
          log.info("Enabling disk cache " + loc.getAbsolutePath());
        } else {
          log.warn("Can't write to disk cache: " + loc.getAbsolutePath());
        }
      } else {
        log.warn("Can't create disk cache: " + loc.getAbsolutePath());
      }
    }

    private void configureDefaultCache() {
      final CacheConfiguration c = new CacheConfiguration();

      c.setMaxElementsInMemory(1024);
      c.setMemoryStoreEvictionPolicyFromObject(MemoryStoreEvictionPolicy.LFU);

      c.setTimeToIdleSeconds(0);
      c.setTimeToLiveSeconds(0 /* infinite */);
      c.setEternal(true);

      if (mgr.getDiskStoreConfiguration() != null) {
        c.setMaxElementsOnDisk(16384);
        c.setOverflowToDisk(false);
        c.setDiskPersistent(false);

        c.setDiskSpoolBufferSizeMB(5);
        c.setDiskExpiryThreadIntervalSeconds(60 * 60);
      }

      mgr.setDefaultCacheConfiguration(c);
    }

    private CacheConfiguration newCache(final String name) {
      try {
        final CacheConfiguration c;
        c = mgr.getDefaultCacheConfiguration().clone();
        c.setName(name);
        return c;
      } catch (CloneNotSupportedException e) {
        throw new ProvisionException("Cannot configure cache " + name, e);
      }
    }
  }
}
