// 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.google.gerrit.pgm;

import static com.google.gerrit.server.schema.DataSourceProvider.Context.SINGLE_USER;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.gerrit.common.IoUtil;
import com.google.gerrit.common.SiteLibraryLoaderUtil;
import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.plugins.JarScanner;
import com.google.gerrit.server.securestore.DefaultSecureStore;
import com.google.gerrit.server.securestore.SecureStore;
import com.google.gerrit.server.securestore.SecureStore.EntryKey;
import com.google.inject.Injector;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SwitchSecureStore extends SiteProgram {
  private static String getSecureStoreClassFromGerritConfig(SitePaths sitePaths) {
    FileBasedConfig cfg = new FileBasedConfig(sitePaths.gerrit_config.toFile(), FS.DETECTED);
    try {
      cfg.load();
    } catch (IOException | ConfigInvalidException e) {
      throw new RuntimeException("Cannot read gerrit.config file", e);
    }
    return cfg.getString("gerrit", null, "secureStoreClass");
  }

  private static final Logger log = LoggerFactory.getLogger(SwitchSecureStore.class);

  @Option(
    name = "--new-secure-store-lib",
    usage = "Path to new SecureStore implementation",
    required = true
  )
  private String newSecureStoreLib;

  @Override
  public int run() throws Exception {
    SitePaths sitePaths = new SitePaths(getSitePath());
    Path newSecureStorePath = Paths.get(newSecureStoreLib);
    if (!Files.exists(newSecureStorePath)) {
      log.error(String.format("File %s doesn't exist", newSecureStorePath.toAbsolutePath()));
      return -1;
    }

    String newSecureStore = getNewSecureStoreClassName(newSecureStorePath);
    String currentSecureStoreName = getCurrentSecureStoreClassName(sitePaths);

    if (currentSecureStoreName.equals(newSecureStore)) {
      log.error(
          "Old and new SecureStore implementation names "
              + "are the same. Migration will not work");
      return -1;
    }

    IoUtil.loadJARs(newSecureStorePath);
    SiteLibraryLoaderUtil.loadSiteLib(sitePaths.lib_dir);

    log.info(
        "Current secureStoreClass property ({}) will be replaced with {}",
        currentSecureStoreName,
        newSecureStore);
    Injector dbInjector = createDbInjector(SINGLE_USER);
    SecureStore currentStore = getSecureStore(currentSecureStoreName, dbInjector);
    SecureStore newStore = getSecureStore(newSecureStore, dbInjector);

    migrateProperties(currentStore, newStore);

    removeOldLib(sitePaths, currentSecureStoreName);
    copyNewLib(sitePaths, newSecureStorePath);

    updateGerritConfig(sitePaths, newSecureStore);

    return 0;
  }

  private void migrateProperties(SecureStore currentStore, SecureStore newStore) {
    log.info("Migrate entries");
    for (EntryKey key : currentStore.list()) {
      String[] value = currentStore.getList(key.section, key.subsection, key.name);
      if (value != null) {
        newStore.setList(key.section, key.subsection, key.name, Arrays.asList(value));
      } else {
        String msg = String.format("Cannot migrate entry for %s", key.section);
        if (key.subsection != null) {
          msg = msg + String.format(".%s", key.subsection);
        }
        msg = msg + String.format(".%s", key.name);
        throw new RuntimeException(msg);
      }
    }
  }

  private void removeOldLib(SitePaths sitePaths, String currentSecureStoreName) throws IOException {
    Path oldSecureStore = findJarWithSecureStore(sitePaths, currentSecureStoreName);
    if (oldSecureStore != null) {
      log.info("Removing old SecureStore ({}) from lib/ directory", oldSecureStore.getFileName());
      try {
        Files.delete(oldSecureStore);
      } catch (IOException e) {
        log.error("Cannot remove {}", oldSecureStore.toAbsolutePath(), e);
      }
    } else {
      log.info(
          "Cannot find jar with old SecureStore ({}) in lib/ directory", currentSecureStoreName);
    }
  }

  private void copyNewLib(SitePaths sitePaths, Path newSecureStorePath) throws IOException {
    log.info("Copy new SecureStore ({}) into lib/ directory", newSecureStorePath.getFileName());
    Files.copy(newSecureStorePath, sitePaths.lib_dir.resolve(newSecureStorePath.getFileName()));
  }

  private void updateGerritConfig(SitePaths sitePaths, String newSecureStore)
      throws IOException, ConfigInvalidException {
    log.info("Set gerrit.secureStoreClass property of gerrit.config to {}", newSecureStore);
    FileBasedConfig config = new FileBasedConfig(sitePaths.gerrit_config.toFile(), FS.DETECTED);
    config.load();
    config.setString("gerrit", null, "secureStoreClass", newSecureStore);
    config.save();
  }

  private String getNewSecureStoreClassName(Path secureStore) throws IOException {
    try (JarScanner scanner = new JarScanner(secureStore)) {
      List<String> newSecureStores = scanner.findSubClassesOf(SecureStore.class);
      if (newSecureStores.isEmpty()) {
        throw new RuntimeException(
            String.format(
                "Cannot find implementation of SecureStore interface in %s",
                secureStore.toAbsolutePath()));
      }
      if (newSecureStores.size() > 1) {
        throw new RuntimeException(
            String.format(
                "Found too many implementations of SecureStore:\n%s\nin %s",
                Joiner.on("\n").join(newSecureStores), secureStore.toAbsolutePath()));
      }
      return Iterables.getOnlyElement(newSecureStores);
    }
  }

  private String getCurrentSecureStoreClassName(SitePaths sitePaths) {
    String current = getSecureStoreClassFromGerritConfig(sitePaths);
    if (!Strings.isNullOrEmpty(current)) {
      return current;
    }
    return DefaultSecureStore.class.getName();
  }

  private SecureStore getSecureStore(String className, Injector injector) {
    try {
      @SuppressWarnings("unchecked")
      Class<? extends SecureStore> clazz = (Class<? extends SecureStore>) Class.forName(className);
      return injector.getInstance(clazz);
    } catch (ClassNotFoundException e) {
      throw new RuntimeException(
          String.format("Cannot load SecureStore implementation: %s", className), e);
    }
  }

  private Path findJarWithSecureStore(SitePaths sitePaths, String secureStoreClass)
      throws IOException {
    List<Path> jars = SiteLibraryLoaderUtil.listJars(sitePaths.lib_dir);
    String secureStoreClassPath = secureStoreClass.replace('.', '/') + ".class";
    for (Path jar : jars) {
      try (JarFile jarFile = new JarFile(jar.toFile())) {
        ZipEntry entry = jarFile.getEntry(secureStoreClassPath);
        if (entry != null) {
          return jar;
        }
      } catch (IOException e) {
        log.error(e.getMessage(), e);
      }
    }
    return null;
  }
}
