// 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.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 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(SpannerLifeCycleManager.class);
    install(
        new FactoryModuleBuilder()
            .implement(AutoCloseable.class, Lock.class)
            .build(Lock.LockFactory.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 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;
  }
}
