// 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.server.schema;

import static com.google.gerrit.server.config.ConfigUtil.getEnum;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

import com.google.gerrit.lifecycle.LifecycleListener;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gwtorm.jdbc.SimpleDataSource;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;

import org.apache.commons.dbcp.BasicDataSource;
import org.eclipse.jgit.lib.Config;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

/** Provides access to the DataSource. */
@Singleton
public final class DataSourceProvider implements Provider<DataSource>,
    LifecycleListener {
  private final DataSource ds;

  @Inject
  DataSourceProvider(final SitePaths site,
      @GerritServerConfig final Config cfg, Context ctx) {
    ds = open(site, cfg, ctx);
  }

  @Override
  public synchronized DataSource get() {
    return ds;
  }

  @Override
  public void start() {
  }

  @Override
  public synchronized void stop() {
    if (ds instanceof BasicDataSource) {
      try {
        ((BasicDataSource) ds).close();
      } catch (SQLException e) {
        // Ignore the close failure.
      }
    }
  }

  public static enum Context {
    SINGLE_USER, MULTI_USER;
  }

  public static enum Type {
    H2, POSTGRESQL, MYSQL, JDBC;
  }

  private DataSource open(final SitePaths site, final Config cfg,
      final Context context) {
    Type type = getEnum(cfg, "database", null, "type", Type.values(), null);
    String driver = optional(cfg, "driver");
    String url = optional(cfg, "url");
    String username = optional(cfg, "username");
    String password = optional(cfg, "password");

    if (url == null || url.isEmpty()) {
      if (type == null) {
        type = Type.H2;
      }

      switch (type) {
        case H2: {
          String database = optional(cfg, "database");
          if (database == null || database.isEmpty()) {
            database = "db/ReviewDB";
          }
          File db = site.resolve(database);
          try {
            db = db.getCanonicalFile();
          } catch (IOException e) {
            db = db.getAbsoluteFile();
          }
          url = "jdbc:h2:" + db.toURI().toString();
          break;
        }

        case POSTGRESQL: {
          final StringBuilder b = new StringBuilder();
          b.append("jdbc:postgresql://");
          b.append(hostname(optional(cfg, "hostname")));
          b.append(port(optional(cfg, "port")));
          b.append("/");
          b.append(required(cfg, "database"));
          url = b.toString();
          break;
        }

        case MYSQL: {
          final StringBuilder b = new StringBuilder();
          b.append("jdbc:mysql://");
          b.append(hostname(optional(cfg, "hostname")));
          b.append(port(optional(cfg, "port")));
          b.append("/");
          b.append(required(cfg, "database"));
          url = b.toString();
          break;
        }

        case JDBC:
          driver = required(cfg, "driver");
          url = required(cfg, "url");
          break;

        default:
          throw new IllegalArgumentException(type + " not supported");
      }
    }

    if (driver == null || driver.isEmpty()) {
      if (url.startsWith("jdbc:h2:")) {
        driver = "org.h2.Driver";

      } else if (url.startsWith("jdbc:postgresql:")) {
        driver = "org.postgresql.Driver";

      } else if (url.startsWith("jdbc:mysql:")) {
        driver = "com.mysql.jdbc.Driver";

      } else {
        throw new IllegalArgumentException("database.driver must be set");
      }
    }

    boolean usePool;
    if (url.startsWith("jdbc:mysql:")) {
      // MySQL has given us trouble with the connection pool,
      // sometimes the backend disconnects and the pool winds
      // up with a stale connection. Fortunately opening up
      // a new MySQL connection is usually very fast.
      //
      usePool = false;
    } else {
      usePool = true;
    }
    usePool = cfg.getBoolean("database", "connectionpool", usePool);
    if (context == Context.SINGLE_USER) {
      usePool = false;
    }

    if (usePool) {
      final BasicDataSource ds = new BasicDataSource();
      ds.setDriverClassName(driver);
      ds.setUrl(url);
      if (username != null && !username.isEmpty()) {
        ds.setUsername(username);
      }
      if (password != null && !password.isEmpty()) {
        ds.setPassword(password);
      }
      ds.setMaxActive(cfg.getInt("database", "poollimit", 8));
      ds.setMinIdle(cfg.getInt("database", "poolminidle", 4));
      ds.setMaxIdle(cfg.getInt("database", "poolmaxidle", 4));
      ds.setMaxWait(ConfigUtil.getTimeUnit(cfg, "database", null,
          "poolmaxwait", MILLISECONDS.convert(30, SECONDS), MILLISECONDS));
      ds.setInitialSize(ds.getMinIdle());
      return ds;

    } else {
      // Don't use the connection pool.
      //
      try {
        final Properties p = new Properties();
        p.setProperty("driver", driver);
        p.setProperty("url", url);
        if (username != null) {
          p.setProperty("user", username);
        }
        if (password != null) {
          p.setProperty("password", password);
        }
        return new SimpleDataSource(p);
      } catch (SQLException se) {
        throw new ProvisionException("Database unavailable", se);
      }
    }
  }

  private static String hostname(String hostname) {
    if (hostname == null || hostname.isEmpty()) {
      hostname = "localhost";

    } else if (hostname.contains(":") && !hostname.startsWith("[")) {
      hostname = "[" + hostname + "]";
    }
    return hostname;
  }

  private static String port(String port) {
    if (port != null && !port.isEmpty()) {
      return ":" + port;
    }
    return "";
  }

  private static String optional(final Config config, final String name) {
    return config.getString("database", null, name);
  }

  private static String required(final Config config, final String name) {
    final String v = optional(config, name);
    if (v == null || "".equals(v)) {
      throw new IllegalArgumentException("No database." + name + " configured");
    }
    return v;
  }
}
