// Copyright (C) 2014 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.websession.flatfile;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheStats;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.httpd.WebSessionManager;
import com.google.gerrit.httpd.WebSessionManager.Val;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;

@Singleton
public class FlatFileWebSessionCache implements
    Cache<String, WebSessionManager.Val> {
  private static final Logger log = LoggerFactory
      .getLogger(FlatFileWebSessionCache.class);

  private final File dir;

  @Inject
  public FlatFileWebSessionCache(SitePaths site, PluginConfigFactory cfg) {
    dir = new File(cfg.getFromGerritConfig("websession-flatfile")
        .getString("directory", site.site_path + "/websessions"));
    if (!dir.exists()) {
      log.info(dir + " not found. Creating it.");
      dir.mkdir();
    }
  }

  @Override
  public ConcurrentMap<String, Val> asMap() {
    ConcurrentMap<String, Val> map = new ConcurrentHashMap<>();
    File[] files = dir.listFiles();
    if (files == null) {
      return map;
    }
    for (File f : files) {
      Val v = readFile(f);
      if (v != null) {
        map.put(f.getName(), v);
      }
    }
    return map;
  }

  @Override
  public void cleanUp() {
    // do nothing
  }

  @Override
  public Val get(String key, Callable<? extends Val> valueLoader)
      throws ExecutionException {
    Val value = getIfPresent(key);
    if (value == null) {
      try {
        value = valueLoader.call();
      } catch (Exception e) {
        throw new ExecutionException(e);
      }
    }
    return value;
  }

  @Override
  public ImmutableMap<String, Val> getAllPresent(Iterable<?> keys) {
    ImmutableMap.Builder<String, Val> mapBuilder =
        new ImmutableMap.Builder<>();
    for (Object key : keys) {
      Val v = getIfPresent(key);
      if (v != null) {
        mapBuilder.put((String) key, v);
      }
    }
    return mapBuilder.build();
  }

  @Override
  @Nullable
  public Val getIfPresent(Object key) {
    if (key instanceof String) {
      File f = new File(dir, (String) key);
      return readFile(f);
    }
    return null;
  }

  @Override
  public void invalidate(Object key) {
    if (key instanceof String) {
      deleteFile(new File(dir, (String) key));
    }
  }

  @Override
  public void invalidateAll() {
    File[] files = dir.listFiles();
    if (files != null) {
      for (File f : files) {
        deleteFile(f);
      }
    }
  }

  @Override
  public void invalidateAll(Iterable<?> keys) {
    for (Object key : keys) {
      invalidate(key);
    }
  }

  @Override
  public void put(String key, Val value) {
    File tempFile = null;
    try {
      tempFile = File.createTempFile(UUID.randomUUID().toString(), null, dir);
      try (OutputStream fileStream = new FileOutputStream(tempFile);
          ObjectOutputStream objStream = new ObjectOutputStream(fileStream)) {
        objStream.writeObject(value);

        File f = new File(dir, key);
        if (!tempFile.renameTo(f)) {
          log.warn("Cannot put into cache " + dir.getAbsolutePath()
              + "; error renaming temp file");
        }
      }
    } catch (FileNotFoundException e) {
      log.warn("Cannot put into cache " + dir.getAbsolutePath(), e);
    } catch (IOException e) {
      log.warn("Cannot put into cache " + dir.getAbsolutePath(), e);
    } finally {
      if (tempFile != null) {
        deleteFile(tempFile);
      }
    }
  }

  @Override
  public void putAll(Map<? extends String, ? extends Val> keys) {
    for (Entry<? extends String, ? extends Val> e : keys.entrySet()) {
      put(e.getKey(), e.getValue());
    }
  }

  @Override
  public long size() {
    String[] files = dir.list();
    if (files == null) {
      return 0;
    }
    return files.length;
  }

  @Override
  public CacheStats stats() {
    log.warn("stats() unimplemented");
    return null;
  }

  private Val readFile(File f) {
    try (InputStream fileStream = new FileInputStream(f);
        ObjectInputStream objStream = new ObjectInputStream(fileStream)) {
        return (Val) objStream.readObject();
    } catch (ClassNotFoundException e) {
      log.warn("Entry " + f.getName() + " in cache " + dir.getAbsolutePath()
          + " has an incompatible class and can't be deserialized. "
          + "Invalidating entry.");
      invalidate(f.getName());
    } catch (IOException e) {
      log.warn("Cannot read cache " + dir.getAbsolutePath(), e);
    }
    return null;
  }

  private void deleteFile(File f) {
    if (f.exists() && !f.delete()) {
      log.warn("Cannot delete file " + f.getName() + " from cache "
          + dir.getAbsolutePath());
    }
  }
}
