// Copyright (C) 2023 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.spannerrefdb;

import com.gerritforge.gerrit.globalrefdb.GlobalRefDatabase;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.spanner.DatabaseAdminClient;
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.DatabaseId;
import com.google.cloud.spanner.SpannerOptions;
import com.google.common.base.Strings;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jgit.lib.Config;

class Module extends LifecycleModule {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static final String DATABASE_KEY = "database";
  public static final String INSTANCE_KEY = "instance";
  public static final String EMULATOR_KEY = "useEmulator";
  public static final String CREDENTIALS_KEY = "credentialsPath";
  public static final String SECTION = "ref-database";
  public static final String SUBSECTION = "spanner";

  @Override
  protected void configure() {
    logger.atInfo().log("Configuring Cloud Spanner for global refdb.");
    DynamicItem.bind(binder(), GlobalRefDatabase.class)
        .to(SpannerRefDatabase.class)
        .in(Scopes.SINGLETON);
    listener().to(DatabaseSchemaCreator.class);
    install(new FactoryModuleBuilder().build(Lock.Factory.class));
    bind(ScheduledExecutorService.class)
        .annotatedWith(HeartbeatExecutor.class)
        .toProvider(HeartbeatExecutorProvider.class)
        .in(Scopes.SINGLETON);
    listener().to(HeartbeatExecutorProvider.class);
  }

  @Provides
  @Singleton
  private Config Configuration(PluginConfigFactory configFactory, @PluginName String pluginName) {
    return configFactory.getGlobalPluginConfig(pluginName);
  }

  @Provides
  @Singleton
  public SpannerOptions createSpannerOptions(Config cfg) throws FileNotFoundException, IOException {
    SpannerOptions options;
    boolean useEmulator = cfg.getBoolean(SECTION, SUBSECTION, EMULATOR_KEY, false);
    if (useEmulator) {
      options = SpannerOptions.newBuilder().build();
      logger.atInfo().log(
          "Using local Spanner emulator for global-refdb; Spanner credentials will not be read.");
    } else {
      String credentialsPath = getString(cfg, SECTION, SUBSECTION, CREDENTIALS_KEY, null);
      GoogleCredentials credentials =
          GoogleCredentials.fromStream(new FileInputStream(credentialsPath));
      options = SpannerOptions.newBuilder().setCredentials(credentials).build();
    }
    return options;
  }

  @Provides
  @Singleton
  public DatabaseAdminClient createDbAdminClient(SpannerOptions options) {
    return options.getService().getDatabaseAdminClient();
  }

  @Provides
  @Singleton
  public DatabaseClient createDatabaseClient(Config cfg, SpannerOptions options) {
    return options.getService().getDatabaseClient(createDatabaseId(cfg, options));
  }

  @Provides
  @Singleton
  public DatabaseId createDatabaseId(Config cfg, SpannerOptions options) {
    String spannerInstance = getString(cfg, SECTION, SUBSECTION, INSTANCE_KEY, "spanner-instance");
    String spannerDatabase = getString(cfg, SECTION, SUBSECTION, DATABASE_KEY, "global-refdb");

    return DatabaseId.of(options.getProjectId(), spannerInstance, spannerDatabase);
  }

  private String getString(
      Config cfg, String section, String subsection, String name, String defaultValue) {
    String value = cfg.getString(section, subsection, name);
    if (!Strings.isNullOrEmpty(value)) {
      return value;
    }
    return defaultValue;
  }
}
