// Copyright (C) 2013 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 static com.google.inject.Scopes.SINGLETON;
import static com.google.inject.Stage.PRODUCTION;

import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Die;
import com.google.gerrit.common.JarUtil;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.index.IndexType;
import com.google.gerrit.metrics.DisabledMetricMaker;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.init.api.InitFlags;
import com.google.gerrit.pgm.init.api.InstallAllPlugins;
import com.google.gerrit.pgm.init.api.InstallPlugins;
import com.google.gerrit.pgm.init.api.LibraryDownload;
import com.google.gerrit.pgm.init.index.IndexManagerOnInit;
import com.google.gerrit.pgm.init.index.IndexModuleOnInit;
import com.google.gerrit.pgm.init.index.lucene.LuceneIndexModuleOnInit;
import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.server.config.GerritServerConfigModule;
import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.IndexModule;
import com.google.gerrit.server.plugins.JarScanner;
import com.google.gerrit.server.schema.NoteDbSchemaUpdater;
import com.google.gerrit.server.schema.UpdateUI;
import com.google.gerrit.server.securestore.SecureStore;
import com.google.gerrit.server.securestore.SecureStoreClassName;
import com.google.gerrit.server.securestore.SecureStoreProvider;
import com.google.inject.AbstractModule;
import com.google.inject.CreationException;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.Message;
import com.google.inject.util.Providers;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/** Initialize a new Gerrit installation. */
public class BaseInit extends SiteProgram {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final boolean standalone;
  protected final PluginsDistribution pluginsDistribution;
  private final List<String> pluginsToInstall;

  private Injector sysInjector;

  protected BaseInit(PluginsDistribution pluginsDistribution, List<String> pluginsToInstall) {
    this.standalone = true;
    this.pluginsDistribution = pluginsDistribution;
    this.pluginsToInstall = pluginsToInstall;
  }

  public BaseInit(
      Path sitePath,
      boolean standalone,
      PluginsDistribution pluginsDistribution,
      List<String> pluginsToInstall) {
    super(sitePath);
    this.standalone = standalone;
    this.pluginsDistribution = pluginsDistribution;
    this.pluginsToInstall = pluginsToInstall;
  }

  @Override
  public int run() throws Exception {
    final SiteInit init = createSiteInit();
    if (beforeInit(init)) {
      return 0;
    }

    init.flags.autoStart = getAutoStart() && init.site.isNew;
    init.flags.dev = isDev() && init.site.isNew;
    init.flags.skipPlugins = skipPlugins();
    init.flags.deleteCaches = getDeleteCaches();
    init.flags.isNew = init.site.isNew;

    final SiteRun run;
    try {
      init.initializer.run();
      init.flags.deleteOnFailure = false;

      Injector sysInjector = createSysInjector(init);
      IndexManagerOnInit indexManager = sysInjector.getInstance(IndexManagerOnInit.class);
      try {
        indexManager.start();
        run = createSiteRun(init);
        try {
          run.upgradeSchema();
        } catch (StorageException e) {
          String msg = "Couldn't upgrade schema. Expected if slave and read-only database";
          System.err.println(msg);
          logger.atSevere().withCause(e).log("%s", msg);
        }

        init.initializer.postRun(sysInjector);
      } finally {
        indexManager.stop();
      }
    } catch (Exception | Error failure) {
      if (init.flags.deleteOnFailure) {
        recursiveDelete(getSitePath());
      }
      throw failure;
    }

    System.err.println("Initialized " + getSitePath().toRealPath().normalize());
    afterInit(run);
    return 0;
  }

  protected boolean skipPlugins() {
    return false;
  }

  protected String getSecureStoreLib() {
    return null;
  }

  protected boolean skipAllDownloads() {
    return false;
  }

  protected List<String> getSkippedDownloads() {
    return Collections.emptyList();
  }

  /**
   * Invoked before site init is called.
   *
   * @param init initializer instance.
   */
  protected boolean beforeInit(SiteInit init) throws Exception {
    return false;
  }

  /**
   * Invoked after site init is called.
   *
   * @param run completed run instance.
   */
  protected void afterInit(SiteRun run) throws Exception {}

  @Nullable
  protected List<String> getInstallPlugins() {
    try {
      if (pluginsToInstall != null && pluginsToInstall.isEmpty()) {
        return Collections.emptyList();
      }
      List<String> names = pluginsDistribution.listPluginNames();
      if (pluginsToInstall != null) {
        names.removeIf(n -> !pluginsToInstall.contains(n));
      }
      return names;
    } catch (FileNotFoundException e) {
      logger.atWarning().log(
          "Couldn't find distribution archive location. No plugin will be installed");
      return null;
    }
  }

  protected boolean installAllPlugins() {
    return false;
  }

  protected boolean getAutoStart() {
    return false;
  }

  public static class SiteInit {
    public final SitePaths site;
    final InitFlags flags;
    final ConsoleUI ui;
    final SitePathInitializer initializer;

    @Inject
    SiteInit(
        final SitePaths site,
        final InitFlags flags,
        final ConsoleUI ui,
        final SitePathInitializer initializer) {
      this.site = site;
      this.flags = flags;
      this.ui = ui;
      this.initializer = initializer;
    }
  }

  private SiteInit createSiteInit() {
    final ConsoleUI ui = getConsoleUI();
    final Path sitePath = getSitePath();
    final List<Module> m = new ArrayList<>();
    final SecureStoreInitData secureStoreInitData = discoverSecureStoreClass();
    final String currentSecureStoreClassName = getConfiguredSecureStoreClass();

    if (secureStoreInitData != null
        && currentSecureStoreClassName != null
        && !currentSecureStoreClassName.equals(secureStoreInitData.className)) {
      String err =
          String.format(
              "Different secure store was previously configured: %s. "
                  + "Use SwitchSecureStore program to switch between implementations.",
              currentSecureStoreClassName);
      throw die(err);
    }

    m.add(new GerritServerConfigModule());
    m.add(new InitModule(standalone));
    m.add(
        new AbstractModule() {
          @Override
          protected void configure() {
            bind(ConsoleUI.class).toInstance(ui);
            bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath);
            List<String> plugins = MoreObjects.firstNonNull(getInstallPlugins(), new ArrayList<>());
            bind(new TypeLiteral<List<String>>() {})
                .annotatedWith(InstallPlugins.class)
                .toInstance(plugins);
            bind(new TypeLiteral<Boolean>() {})
                .annotatedWith(InstallAllPlugins.class)
                .toInstance(installAllPlugins());
            bind(PluginsDistribution.class).toInstance(pluginsDistribution);

            String secureStoreClassName;
            if (secureStoreInitData != null) {
              secureStoreClassName = secureStoreInitData.className;
            } else {
              secureStoreClassName = currentSecureStoreClassName;
            }
            if (secureStoreClassName != null) {
              ui.message("Using secure store: %s\n", secureStoreClassName);
            }
            bind(SecureStoreInitData.class).toProvider(Providers.of(secureStoreInitData));
            bind(String.class)
                .annotatedWith(SecureStoreClassName.class)
                .toProvider(Providers.of(secureStoreClassName));
            bind(SecureStore.class).toProvider(SecureStoreProvider.class).in(SINGLETON);
            bind(new TypeLiteral<List<String>>() {})
                .annotatedWith(LibraryDownload.class)
                .toInstance(getSkippedDownloads());
            bind(Boolean.class).annotatedWith(LibraryDownload.class).toInstance(skipAllDownloads());

            bind(MetricMaker.class).to(DisabledMetricMaker.class);
          }
        });

    try {
      return Guice.createInjector(PRODUCTION, m).getInstance(SiteInit.class);
    } catch (CreationException ce) {
      final Message first = ce.getErrorMessages().iterator().next();
      Throwable why = first.getCause();

      if (why instanceof Die) {
        throw (Die) why;
      }

      final StringBuilder buf = new StringBuilder(ce.getMessage());
      while (why != null) {
        buf.append("\n");
        buf.append(why.getMessage());
        why = why.getCause();
        if (why != null) {
          buf.append("\n  caused by ");
        }
      }
      throw die(buf.toString(), new RuntimeException("InitInjector failed", ce));
    }
  }

  protected ConsoleUI getConsoleUI() {
    return ConsoleUI.getInstance(false);
  }

  @Nullable
  private SecureStoreInitData discoverSecureStoreClass() {
    String secureStore = getSecureStoreLib();
    if (Strings.isNullOrEmpty(secureStore)) {
      return null;
    }

    Path secureStoreLib = Path.of(secureStore);
    if (!Files.exists(secureStoreLib)) {
      throw new InvalidSecureStoreException(String.format("File %s doesn't exist", secureStore));
    }
    try (JarScanner scanner = new JarScanner(secureStoreLib)) {
      List<String> secureStores = scanner.findSubClassesOf(SecureStore.class);
      if (secureStores.isEmpty()) {
        throw new InvalidSecureStoreException(
            String.format(
                "Cannot find class implementing %s interface in %s",
                SecureStore.class.getName(), secureStore));
      }
      if (secureStores.size() > 1) {
        throw new InvalidSecureStoreException(
            String.format(
                "%s has more that one implementation of %s interface",
                secureStore, SecureStore.class.getName()));
      }
      JarUtil.loadJars(secureStoreLib);
      return new SecureStoreInitData(secureStoreLib, secureStores.get(0));
    } catch (IOException e) {
      throw new InvalidSecureStoreException(String.format("%s is not a valid jar", secureStore), e);
    }
  }

  public static class SiteRun {
    public final ConsoleUI ui;
    public final SitePaths site;
    public final InitFlags flags;
    final NoteDbSchemaUpdater noteDbSchemaUpdater;
    final GitRepositoryManager repositoryManager;

    @Inject
    SiteRun(
        ConsoleUI ui,
        SitePaths site,
        InitFlags flags,
        NoteDbSchemaUpdater noteDbSchemaUpdater,
        GitRepositoryManager repositoryManager) {
      this.ui = ui;
      this.site = site;
      this.flags = flags;
      this.noteDbSchemaUpdater = noteDbSchemaUpdater;
      this.repositoryManager = repositoryManager;
    }

    void upgradeSchema() {
      noteDbSchemaUpdater.update(new UpdateUIImpl(ui));
    }

    private static class UpdateUIImpl implements UpdateUI {
      private final ConsoleUI consoleUi;

      UpdateUIImpl(ConsoleUI consoleUi) {
        this.consoleUi = consoleUi;
      }

      @Override
      public void message(String message) {
        System.err.println(message);
        System.err.flush();
      }

      @Override
      public boolean yesno(boolean defaultValue, String message) {
        return consoleUi.yesno(defaultValue, message);
      }

      @Override
      public void waitForUser() {
        consoleUi.waitForUser();
      }

      @Override
      public String readString(String defaultValue, Set<String> allowedValues, String message) {
        return consoleUi.readString(defaultValue, allowedValues, message);
      }

      @Override
      public boolean isBatch() {
        return consoleUi.isBatch();
      }
    }
  }

  private SiteRun createSiteRun(SiteInit init) {
    return createSysInjector(init).getInstance(SiteRun.class);
  }

  private Injector createSysInjector(SiteInit init) {
    if (sysInjector == null) {
      final List<Module> modules = new ArrayList<>();
      modules.add(
          new AbstractModule() {
            @Override
            protected void configure() {
              bind(ConsoleUI.class).toInstance(init.ui);
              bind(InitFlags.class).toInstance(init.flags);
            }
          });
      Injector dbInjector = createDbInjector();

      IndexType indexType = IndexModule.getIndexType(dbInjector);
      if (indexType.isLucene()) {
        modules.add(new LuceneIndexModuleOnInit());
      } else if (indexType.isFake()) {
        try {
          Class<?> clazz = Class.forName("com.google.gerrit.index.testing.FakeIndexModuleOnInit");
          Module indexOnInitModule = (Module) clazz.getDeclaredConstructor().newInstance();
          modules.add(indexOnInitModule);
        } catch (InstantiationException
            | IllegalAccessException
            | ClassNotFoundException
            | NoSuchMethodException
            | InvocationTargetException e) {
          throw new IllegalStateException("unable to create fake index", e);
        }
        modules.add(new IndexModuleOnInit());
      } else {
        throw new IllegalStateException("unsupported index.type = " + indexType);
      }
      sysInjector = dbInjector.createChildInjector(modules);
    }
    return sysInjector;
  }

  private static void recursiveDelete(Path path) {
    final String msg = "warn: Cannot remove ";
    try {
      Files.walkFileTree(
          path,
          new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path f, BasicFileAttributes attrs) throws IOException {
              try {
                Files.delete(f);
              } catch (IOException e) {
                System.err.println(msg + f);
              }
              return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException err) {
              try {
                // Previously warned if err was not null; if dir is not empty as a
                // result, will cause an error that will be logged below.
                Files.delete(dir);
              } catch (IOException e) {
                System.err.println(msg + dir);
              }
              return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path f, IOException e) {
              System.err.println(msg + f);
              return FileVisitResult.CONTINUE;
            }
          });
    } catch (IOException e) {
      System.err.println(msg + path);
    }
  }

  protected boolean isDev() {
    return false;
  }

  protected boolean getDeleteCaches() {
    return false;
  }
}
