package com.atlassian.stash.internal.hibernate.dialect.resolver;

import com.atlassian.stash.internal.hibernate.dialect.*;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.Oracle10gDialect;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A custom {@code AbstractDialectResolver} implementation which returns customised {@code Dialect} implementations
 * that "adjust" certain Hibernate choices to allow Stash to work properly with its supported database types. Further
 * details about what each customised dialect does can be found in the documentation for that dialect.
 *
 * @since 2.0
 * @see CustomMySqlDialect
 * @see CustomPostgres81Dialect
 * @see CustomPostgres82Dialect
 * @see CustomPostgres9Dialect
 * @see CustomSqlServer2005Dialect
 * @see CustomSqlServer2008Dialect
 * @see CustomSqlServer2012Dialect
 * @see CustomSqlServerDialect
 */
public class CustomDialectResolver implements DialectResolver {

    private static final Logger log = LoggerFactory.getLogger(CustomDialectResolver.class);

    @Override
    public Dialect resolveDialect(DialectResolutionInfo info) {
        String databaseName = info.getDatabaseName();

        if ("H2".equals(databaseName)) {
            log.debug("Returning custom H2 dialect for {}", databaseName);
            return new CustomH2Dialect();
        }
        if ("HSQL Database Engine".equals(databaseName)) {
            log.debug("Returning custom HSQL dialect for {}", databaseName);
            return new CustomHSQLDialect();
        }
        if (databaseName.startsWith("Microsoft SQL Server")) {
            int databaseMajorVersion = info.getDatabaseMajorVersion();
            if (databaseMajorVersion > 10) {
                log.debug("Returning custom SQL Server 2012 dialect for {} (Version: {})",
                        databaseName, databaseMajorVersion);
                return new CustomSqlServer2012Dialect();
            }
            if (databaseMajorVersion == 10) {
                log.debug("Returning custom SQL Server 2008 dialect for {} (Version: {})",
                        databaseName, databaseMajorVersion);
                return new CustomSqlServer2008Dialect();
            }
            if (databaseMajorVersion == 9) {
                log.debug("Returning custom SQL Server 2005 dialect for {} (Version: {})",
                        databaseName, databaseMajorVersion);
                return new CustomSqlServer2005Dialect();
            }
            log.debug("Returning custom SQL Server 2000 dialect for {} (Version: {})",
                    databaseName, databaseMajorVersion);
            return new CustomSqlServerDialect();
        }
        if ("MySQL".equals(databaseName)) {
            log.debug("Returning custom MySQL dialect for {}", databaseName);
            return new CustomMySqlDialect();
        }
        if ("PostgreSQL".equals(databaseName)) {
            int databaseMajorVersion = info.getDatabaseMajorVersion();
            int databaseMinorVersion = info.getDatabaseMinorVersion();
            if (databaseMajorVersion == 9) {
                log.debug("Returning custom PostgreSQL 9 dialect for {} (Version: {}.{})",
                        databaseName, databaseMajorVersion, databaseMinorVersion);
                return new CustomPostgres9Dialect();
            }
            if (databaseMajorVersion == 8 && databaseMinorVersion >= 2) {
                log.debug("Returning custom PostgreSQL 8.2 dialect for {} (Version: {}.{})",
                        databaseName, databaseMajorVersion, databaseMinorVersion);
                return new CustomPostgres82Dialect();
            }
            log.debug("Returning custom PostgreSQL 8.1 dialect for {} (Version: {}.{})",
                    databaseName, databaseMajorVersion, databaseMinorVersion);
            return new CustomPostgres81Dialect();
        }
        // TODO: We should be able to remove this when we upgrade to hibernate 5.0+
        if ("Oracle".equals(databaseName)) {
            int databaseMajorVersion = info.getDatabaseMajorVersion();
            if (databaseMajorVersion > 9) {
                log.debug("Returning Oracle 10g dialect for {} (Version: {})",
                        databaseName, databaseMajorVersion);

                return new CustomOracle10gDialect();
            }
        }

        return null;
    }
}
