// 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.testutil;

import static com.google.common.truth.Truth.assertThat;

import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.pgm.init.index.elasticsearch.ElasticIndexModuleOnInit;
import com.google.gerrit.pgm.init.index.lucene.LuceneIndexModuleOnInit;
import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
import com.google.gerrit.reviewdb.client.SystemConfig;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.index.IndexModule;
import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.schema.SchemaVersion;
import com.google.gwtorm.jdbc.Database;
import com.google.gwtorm.jdbc.SimpleDataSource;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.eclipse.jgit.errors.ConfigInvalidException;

/**
 * An in-memory test instance of {@link ReviewDb} database.
 *
 * <p>Test classes should create one instance of this class for each unique test database they want
 * to use. When the tests needing this instance are complete, ensure that {@link
 * #drop(InMemoryDatabase)} is called to free the resources so the JVM running the unit tests
 * doesn't run out of heap space.
 */
public class InMemoryDatabase implements SchemaFactory<ReviewDb> {
  public static InMemoryDatabase newDatabase(LifecycleManager lifecycle) {
    Injector injector = Guice.createInjector(new InMemoryModule());
    lifecycle.add(injector);
    return injector.getInstance(InMemoryDatabase.class);
  }

  private static int dbCnt;

  private static synchronized DataSource newDataSource() throws SQLException {
    final Properties p = new Properties();
    p.setProperty("driver", org.h2.Driver.class.getName());
    p.setProperty("url", "jdbc:h2:mem:Test_" + (++dbCnt));
    return new SimpleDataSource(p);
  }

  /** Drop the database from memory; does nothing if the instance was null. */
  public static void drop(InMemoryDatabase db) {
    if (db != null) {
      db.drop();
    }
  }

  private final SchemaCreator schemaCreator;

  private Connection openHandle;
  private Database<ReviewDb> database;
  private boolean created;

  @Inject
  InMemoryDatabase(Injector injector) throws OrmException {
    Injector childInjector =
        injector.createChildInjector(
            new AbstractModule() {
              @Override
              protected void configure() {
                switch (IndexModule.getIndexType(injector)) {
                  case LUCENE:
                    install(new LuceneIndexModuleOnInit());
                    break;
                  case ELASTICSEARCH:
                    install(new ElasticIndexModuleOnInit());
                    break;
                  default:
                    throw new IllegalStateException("unsupported index.type");
                }
              }
            });
    this.schemaCreator = childInjector.getInstance(SchemaCreator.class);
    initDatabase();
  }

  InMemoryDatabase(SchemaCreator schemaCreator) throws OrmException {
    this.schemaCreator = schemaCreator;
    initDatabase();
  }

  private void initDatabase() throws OrmException {
    try {
      DataSource dataSource = newDataSource();

      // Open one connection. This will peg the database into memory
      // until someone calls drop on us, allowing subsequent connections
      // opened against the same URL to go to the same set of tables.
      //
      openHandle = dataSource.getConnection();

      // Build the access layer around the connection factory.
      //
      database = new Database<>(dataSource, ReviewDb.class);

    } catch (SQLException e) {
      throw new OrmException(e);
    }
  }

  public Database<ReviewDb> getDatabase() {
    return database;
  }

  @Override
  public ReviewDb open() throws OrmException {
    return getDatabase().open();
  }

  /** Ensure the database schema has been created and initialized. */
  public InMemoryDatabase create() throws OrmException {
    if (!created) {
      created = true;
      try (ReviewDb c = open()) {
        schemaCreator.create(c);
      } catch (IOException | ConfigInvalidException e) {
        throw new OrmException("Cannot create in-memory database", e);
      }
    }
    return this;
  }

  /** Drop this database from memory so it no longer exists. */
  public void drop() {
    if (openHandle != null) {
      try {
        openHandle.close();
      } catch (SQLException e) {
        System.err.println("WARNING: Cannot close database connection");
        e.printStackTrace(System.err);
      }
      openHandle = null;
      database = null;
    }
  }

  public SystemConfig getSystemConfig() throws OrmException {
    try (ReviewDb c = open()) {
      return c.systemConfig().get(new SystemConfig.Key());
    }
  }

  public CurrentSchemaVersion getSchemaVersion() throws OrmException {
    try (ReviewDb c = open()) {
      return c.schemaVersion().get(new CurrentSchemaVersion.Key());
    }
  }

  public void assertSchemaVersion() throws OrmException {
    assertThat(getSchemaVersion().versionNbr).isEqualTo(SchemaVersion.getBinaryVersion());
  }
}
