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

import com.google.common.collect.Lists;
import com.google.gerrit.common.PluginData;
import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.init.api.InitFlags;
import com.google.gerrit.pgm.init.api.InitStep;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.plugins.JarPluginProvider;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

@Singleton
public class InitPlugins implements InitStep {
  public static final String PLUGIN_DIR = "WEB-INF/plugins/";
  public static final String JAR = ".jar";

  public static List<PluginData> listPlugins(SitePaths site,
      PluginsDistribution pluginsDistribution) throws IOException {
    return listPlugins(site, false, pluginsDistribution);
  }

  public static List<PluginData> listPluginsAndRemoveTempFiles(SitePaths site,
      PluginsDistribution pluginsDistribution) throws IOException {
    return listPlugins(site, true, pluginsDistribution);
  }

  private static List<PluginData> listPlugins(final SitePaths site,
      final boolean deleteTempPluginFile, PluginsDistribution pluginsDistribution)
          throws IOException {
    final List<PluginData> result = Lists.newArrayList();
    pluginsDistribution.foreach(new PluginsDistribution.Processor() {
      @Override
      public void process(String pluginName, InputStream in) throws IOException {
        Path tmpPlugin = JarPluginProvider.storeInTemp(pluginName, in, site);
        String pluginVersion = getVersion(tmpPlugin);
        if (deleteTempPluginFile) {
          Files.delete(tmpPlugin);
        }
        result.add(new PluginData(pluginName, pluginVersion, tmpPlugin));
      }
    });
    return result;
  }

  private final ConsoleUI ui;
  private final SitePaths site;
  private final InitFlags initFlags;
  private final InitPluginStepsLoader pluginLoader;
  private final PluginsDistribution pluginsDistribution;

  private Injector postRunInjector;

  @Inject
  InitPlugins(final ConsoleUI ui, final SitePaths site,
      InitFlags initFlags, InitPluginStepsLoader pluginLoader,
      PluginsDistribution pluginsDistribution) {
    this.ui = ui;
    this.site = site;
    this.initFlags = initFlags;
    this.pluginLoader = pluginLoader;
    this.pluginsDistribution = pluginsDistribution;
  }

  @Override
  public void run() throws Exception {
    ui.header("Plugins");

    installPlugins();
    initPlugins();
  }

  @Override
  public void postRun() throws Exception {
    postInitPlugins();
  }

  @Inject(optional = true)
  void setPostRunInjector(Injector injector) {
    postRunInjector = injector;
  }

  private void installPlugins() throws IOException {
    ui.message("Installing plugins.\n");
    List<PluginData> plugins = listPlugins(site, pluginsDistribution);
    for (PluginData plugin : plugins) {
      String pluginName = plugin.name;
      try {
        final Path tmpPlugin = plugin.pluginPath;
        Path p = site.plugins_dir.resolve(plugin.name + ".jar");
        boolean upgrade = Files.exists(p);

        if (!(initFlags.installPlugins.contains(pluginName) || ui.yesno(upgrade,
            "Install plugin %s version %s", pluginName, plugin.version))) {
          Files.deleteIfExists(tmpPlugin);
          continue;
        }

        if (upgrade) {
          final String installedPluginVersion = getVersion(p);
          if (!ui.yesno(upgrade,
              "version %s is already installed, overwrite it",
              installedPluginVersion)) {
            Files.deleteIfExists(tmpPlugin);
            continue;
          }
          try {
            Files.delete(p);
          } catch (IOException e) {
            throw new IOException("Failed to delete plugin " + pluginName
                + ": " + p.toAbsolutePath(), e);
          }
        }
        try {
          Files.move(tmpPlugin, p);
        } catch (IOException e) {
          throw new IOException("Failed to install plugin " + pluginName
              + ": " + tmpPlugin.toAbsolutePath() + " -> "
              + p.toAbsolutePath(), e);
        }
      } finally {
        Files.deleteIfExists(plugin.pluginPath);
      }
    }
    if (plugins.isEmpty()) {
      ui.message("No plugins found to install.\n");
    }
  }

  private void initPlugins() throws Exception {
    ui.message("Initializing plugins.\n");
    Collection<InitStep> initSteps = pluginLoader.getInitSteps();
    if (initSteps.isEmpty()) {
      ui.message("No plugins found with init steps.\n");
    } else {
      for (InitStep initStep : initSteps) {
        initStep.run();
      }
    }
  }

  private void postInitPlugins() throws Exception {
    for (InitStep initStep : pluginLoader.getInitSteps()) {
      postRunInjector.injectMembers(initStep);
      initStep.postRun();
    }
  }

  private static String getVersion(Path plugin) throws IOException {
    try (JarFile jarFile = new JarFile(plugin.toFile())) {
      Manifest manifest = jarFile.getManifest();
      Attributes main = manifest.getMainAttributes();
      return main.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
    }
  }
}
