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

import static com.google.gerrit.server.config.GerritServerConfigModule.getSecureStoreClassName;
import static com.google.inject.Scopes.SINGLETON;
import static com.google.inject.Stage.PRODUCTION;

import com.google.gerrit.common.Die;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.metrics.DisabledMetricMaker;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.dropwizard.DropWizardMetricMaker;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.GerritServerConfigModule;
import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.git.GitRepositoryManagerModule;
import com.google.gerrit.server.notedb.ConfigNotesMigration;
import com.google.gerrit.server.schema.DataSourceModule;
import com.google.gerrit.server.schema.DataSourceProvider;
import com.google.gerrit.server.schema.DataSourceType;
import com.google.gerrit.server.schema.DatabaseModule;
import com.google.gerrit.server.schema.SchemaModule;
import com.google.gerrit.server.securestore.SecureStoreClassName;
import com.google.gwtorm.server.OrmException;
import com.google.inject.AbstractModule;
import com.google.inject.Binding;
import com.google.inject.CreationException;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.google.inject.spi.Message;
import com.google.inject.util.Providers;
import java.lang.annotation.Annotation;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.eclipse.jgit.lib.Config;
import org.kohsuke.args4j.Option;

public abstract class SiteProgram extends AbstractProgram {
  private static final String CONNECTION_ERROR = "Cannot connect to SQL database";

  @Option(
      name = "--site-path",
      aliases = {"-d"},
      usage = "Local directory containing site data")
  private void setSitePath(String path) {
    sitePath = Paths.get(path);
  }

  protected Provider<DataSource> dsProvider;

  private Path sitePath = Paths.get(".");

  protected SiteProgram() {}

  protected SiteProgram(Path sitePath) {
    this.sitePath = sitePath;
  }

  protected SiteProgram(Path sitePath, final Provider<DataSource> dsProvider) {
    this.sitePath = sitePath;
    this.dsProvider = dsProvider;
  }

  /** @return the site path specified on the command line. */
  protected Path getSitePath() {
    return sitePath;
  }

  /** Ensures we are running inside of a valid site, otherwise throws a Die. */
  protected void mustHaveValidSite() throws Die {
    if (!Files.exists(sitePath.resolve("etc").resolve("gerrit.config"))) {
      throw die("not a Gerrit site: '" + getSitePath() + "'\nPerhaps you need to run init first?");
    }
  }

  /** @return provides database connectivity and site path. */
  protected Injector createDbInjector(DataSourceProvider.Context context) {
    return createDbInjector(false, context);
  }

  /** @return provides database connectivity and site path. */
  protected Injector createDbInjector(
      final boolean enableMetrics, final DataSourceProvider.Context context) {
    final List<Module> modules = new ArrayList<>();

    Module sitePathModule =
        new AbstractModule() {
          @Override
          protected void configure() {
            bind(Path.class).annotatedWith(SitePath.class).toInstance(getSitePath());
            bind(String.class)
                .annotatedWith(SecureStoreClassName.class)
                .toProvider(Providers.of(getConfiguredSecureStoreClass()));
          }
        };
    modules.add(sitePathModule);

    if (enableMetrics) {
      modules.add(new DropWizardMetricMaker.ApiModule());
    } else {
      modules.add(
          new AbstractModule() {
            @Override
            protected void configure() {
              bind(MetricMaker.class).to(DisabledMetricMaker.class);
            }
          });
    }

    modules.add(
        new LifecycleModule() {
          @Override
          protected void configure() {
            bind(DataSourceProvider.Context.class).toInstance(context);
            if (dsProvider != null) {
              bind(Key.get(DataSource.class, Names.named("ReviewDb")))
                  .toProvider(dsProvider)
                  .in(SINGLETON);
              if (LifecycleListener.class.isAssignableFrom(dsProvider.getClass())) {
                listener().toInstance((LifecycleListener) dsProvider);
              }
            } else {
              bind(Key.get(DataSource.class, Names.named("ReviewDb")))
                  .toProvider(SiteLibraryBasedDataSourceProvider.class)
                  .in(SINGLETON);
              listener().to(SiteLibraryBasedDataSourceProvider.class);
            }
          }
        });
    Module configModule = new GerritServerConfigModule();
    modules.add(configModule);
    Injector cfgInjector = Guice.createInjector(sitePathModule, configModule);
    Config cfg = cfgInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
    String dbType;
    if (dsProvider != null) {
      dbType = getDbType(dsProvider);
    } else {
      dbType = cfg.getString("database", null, "type");
    }

    if (dbType == null) {
      throw new ProvisionException("database.type must be defined");
    }

    final DataSourceType dst =
        Guice.createInjector(new DataSourceModule(), configModule, sitePathModule)
            .getInstance(Key.get(DataSourceType.class, Names.named(dbType.toLowerCase())));

    modules.add(
        new AbstractModule() {
          @Override
          protected void configure() {
            bind(DataSourceType.class).toInstance(dst);
          }
        });
    modules.add(new DatabaseModule());
    modules.add(new SchemaModule());
    modules.add(cfgInjector.getInstance(GitRepositoryManagerModule.class));
    modules.add(new ConfigNotesMigration.Module());

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

      if (why instanceof SQLException) {
        throw die(CONNECTION_ERROR, why);
      }
      if (why instanceof OrmException
          && why.getCause() != null
          && "Unable to determine driver URL".equals(why.getMessage())) {
        why = why.getCause();
        if (isCannotCreatePoolException(why)) {
          throw die(CONNECTION_ERROR, why.getCause());
        }
        throw die(CONNECTION_ERROR, why);
      }

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

  protected final String getConfiguredSecureStoreClass() {
    return getSecureStoreClassName(sitePath);
  }

  private String getDbType(Provider<DataSource> dsProvider) {
    String dbProductName;
    try (Connection conn = dsProvider.get().getConnection()) {
      dbProductName = conn.getMetaData().getDatabaseProductName().toLowerCase();
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }

    List<Module> modules = new ArrayList<>();
    modules.add(
        new AbstractModule() {
          @Override
          protected void configure() {
            bind(Path.class).annotatedWith(SitePath.class).toInstance(getSitePath());
          }
        });
    modules.add(new GerritServerConfigModule());
    modules.add(new DataSourceModule());
    Injector i = Guice.createInjector(modules);
    List<Binding<DataSourceType>> dsTypeBindings =
        i.findBindingsByType(new TypeLiteral<DataSourceType>() {});
    for (Binding<DataSourceType> binding : dsTypeBindings) {
      Annotation annotation = binding.getKey().getAnnotation();
      if (annotation instanceof Named) {
        Named named = (Named) annotation;
        if (named.value().toLowerCase().contains(dbProductName)) {
          return named.value();
        }
      }
    }
    throw new IllegalStateException(
        String.format(
            "Cannot guess database type from the database product name '%s'", dbProductName));
  }

  @SuppressWarnings("deprecation")
  private static boolean isCannotCreatePoolException(Throwable why) {
    return why instanceof org.apache.commons.dbcp.SQLNestedException
        && why.getCause() != null
        && why.getMessage().startsWith("Cannot create PoolableConnectionFactory");
  }
}
