// 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().build(Lock.Factory.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;
  }
}
