package com.atlassian.stash.internal.ao;

import com.atlassian.activeobjects.spi.DatabaseType;
import com.atlassian.activeobjects.spi.TenantAwareDataSourceProvider;
import com.atlassian.stash.internal.jdbc.DataSourceConfiguration;
import com.atlassian.tenancy.api.Tenant;
import com.google.common.collect.ImmutableMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.sql.DataSource;
import java.util.Map;

import static com.google.common.base.Preconditions.checkNotNull;

public class ApplicationDataSourceProvider implements TenantAwareDataSourceProvider {

    private static final Map<String, DatabaseType> URL_PREFIX_TO_TYPE_MAP = ImmutableMap.<String, DatabaseType>builder()
            .put("jdbc:h2:", DatabaseType.H2)
            .put("jdbc:hsqldb:", DatabaseType.HSQL)
            .put("jdbc:mysql:", DatabaseType.MYSQL)
            .put("jdbc:oracle:", DatabaseType.ORACLE)
            .put("jdbc:postgresql:", DatabaseType.POSTGRESQL)
            .put("jdbc:jtds:sqlserver:", DatabaseType.MS_SQL)
            .put("jdbc:sqlserver:", DatabaseType.MS_SQL)
            .build();

    protected static final Logger log = LoggerFactory.getLogger(ApplicationDataSourceProvider.class);

    private final DataSource dataSource;
    private final DataSourceConfiguration dataSourceConfiguration;

    public ApplicationDataSourceProvider(DataSource dataSource, DataSourceConfiguration dataSourceConfiguration) {
        this.dataSource = dataSource;
        this.dataSourceConfiguration = dataSourceConfiguration;
    }

    @Nonnull
    @Override
    public DataSource getDataSource(@Nonnull Tenant tenant) {
        checkNotNull(tenant, "tenant");
        return dataSource;
    }

    @Nonnull
    @Override
    public DatabaseType getDatabaseType(@Nonnull Tenant tenant) {
        checkNotNull(tenant, "tenant");
        //Note: Do not cache the type; the database can be changed at runtime by database migration.
        String url = dataSourceConfiguration.getUrl();
        if (url != null) {
            for (Map.Entry<String, DatabaseType> entry : URL_PREFIX_TO_TYPE_MAP.entrySet()) {
                if (url.startsWith(entry.getKey())) {
                    return entry.getValue();
                }
            }
        }

        log.warn("Could not determine database type for {}", url);
        return DatabaseType.UNKNOWN;
    }

    @Override
    public String getSchema(@Nonnull Tenant tenant) {
        checkNotNull(tenant, "tenant");
        return null;
    }
}