package au.gov.ga.geodesy.support.spring;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.h2.tools.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import geodb.GeoDB;
import liquibase.integration.spring.SpringLiquibase;

@Configuration
@EnableTransactionManagement

@EnableJpaRepositories(
    value = {"au.gov.ga.geodesy.domain.model"},
    entityManagerFactoryRef = "geodesyEntityManagerFactory",
    transactionManagerRef = "geodesyTransactionManager"
)
public class PersistenceJpaConfig {

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

    private static enum DatabaseType {
        IN_MEMORY, EXTERNAL;
    }

    private static final String DATABASE_TYPE_PROPERTY_NAME = "unitTestDatabaseType";
    private DatabaseType databaseType;

    @Autowired
    private ApplicationContext context;

    public PersistenceJpaConfig() {
        String databaseTypeValue = System.getProperty(DATABASE_TYPE_PROPERTY_NAME);
        if (StringUtils.isBlank(databaseTypeValue)) {
            databaseType = DatabaseType.IN_MEMORY;
        } else {
            databaseType = DatabaseType.valueOf(databaseTypeValue);
        }
        log.info("Database type: " + databaseType);
    }

    @Bean
    @Primary
    /* @DependsOn("liquibase") */
    public LocalContainerEntityManagerFactoryBean geodesyEntityManagerFactory() {
        LocalContainerEntityManagerFactoryBean springFactoryBean = new LocalContainerEntityManagerFactoryBean();
        springFactoryBean.setPackagesToScan(new String[]{"au.gov.ga.geodesy.domain.model"});
        springFactoryBean.setDataSource(dataSource());
        springFactoryBean.setPersistenceUnitName("geodesy");
        JpaVendorAdapter vendor = new HibernateJpaVendorAdapter();
        springFactoryBean.setJpaVendorAdapter(vendor);
        springFactoryBean.setJpaProperties(jpaProperties());
        /* springFactoryBean.setMappingResources("au/gov/ga/geodesy/igssitelog/support/hibernate/hibernate.cfg.xml"); */
        return springFactoryBean;
    }

    @Bean
    public DataSource dataSource() {
        switch (databaseType) {
            case IN_MEMORY: return inMemoryDataSource();
            case EXTERNAL:  return externalDataSource();
            default: return null;
        }
    }

    private DataSource externalDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl("jdbc:oracle:thin:@dm02-scan.prod.lan:7381/ORADEV");
        dataSource.setUsername("u62208");
        dataSource.setPassword("");
        return dataSource;
    }

    private DataSource inMemoryDataSource() {
        System.setProperty("h2.baseDir", "target/");
        final String h2Url = "jdbc:h2:./h2-test-db;INIT=CREATE SCHEMA IF NOT EXISTS U62208;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE";
        DataSource dataSource = new SingleConnectionDataSource() {
            {
                setDriverClassName("org.h2.Driver");
                setUrl(h2Url);
                setSuppressClose(true);
            }

            @Override
            public Connection getConnection() throws SQLException {
                Connection c = super.getConnection();
                GeoDB.InitGeoDB(c);
                return c;
            }
        };
        try {
            Server.createWebServer().start();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dataSource;
    }

    /* @Bean */
    public SpringLiquibase liquibase() {
        if (databaseType == DatabaseType.IN_MEMORY) {
            SpringLiquibase liquibase = new SpringLiquibase();
            liquibase.setDataSource(dataSource());
            liquibase.setChangeLog("classpath:db/geodesy-database-changelog.xml");
            liquibase.setDefaultSchema("u62208");
            return liquibase;
        } else {
            return null;
        }
    }

    @Bean
    public PlatformTransactionManager geodesyTransactionManager(EntityManagerFactory f) {
        JpaTransactionManager transactionManager = new JpaTransactionManager(f);
        transactionManager.setPersistenceUnitName("geodesy");
        return transactionManager;
    }

    private Properties jpaProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.default_schema", "u62208");

        switch (databaseType) {
            case IN_MEMORY:
                properties.setProperty("hibernate.dialect", "org.hibernate.spatial.dialect.h2geodb.GeoDBDialect");
                properties.setProperty("hibernate.hbm2ddl.auto", "create");
                /* properties.setProperty("hibernate.show_sql", "true"); */
                /* properties.setProperty("hibernate.format_sql", "true"); */
                /* properties.setProperty("hibernate.use_sql_comments", "true"); */
                break;
            case EXTERNAL:
                properties.setProperty("hibernate.dialect", "org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect");
                properties.setProperty("hibernate.hbm2ddl.auto", "create");
                break;
            default:
        }
        return properties;
    }
}

@@ -3287,32 +3287,40 @@
  return external
+Postgres
 DataSource();%0A  
@@ -3399,16 +3399,22 @@
 external
+Oracle
 DataSour
@@ -3608,21 +3608,342 @@
 rname(%22u
-62208
+sername%22);%0A        dataSource.setPassword(%22password%22);%0A        return dataSource;%0A    %7D%0A%0A    private DataSource externalPostgresDataSource() %7B%0A        DriverManagerDataSource dataSource = new DriverManagerDataSource();%0A        dataSource.setUrl(%22jdbc:postgresql://localhost/geodesydb%22);%0A        dataSource.setUsername(%22geodesy
 %22);%0A    
@@ -3970,16 +3970,25 @@
 ssword(%22
+geodesypw
 %22);%0A    
@@ -4204,14 +4204,15 @@
 STS 
-U62208
+geodesy
 ;DB_
@@ -5219,22 +5219,23 @@
 Schema(%22
-u62208
+geodesy
 %22);%0A    
@@ -5759,14 +5759,15 @@
 %22, %22
-u62208
+geodesy
 %22);%0A
@@ -6401,31 +6401,23 @@
 ect.
-oracle.OracleSpatial10g
+postgis.Postgis
 Dial
@@ -6491,32 +6491,263 @@
 to%22, %22create%22);%0A
+//                properties.setProperty(%22hibernate.show_sql%22, %22true%22);%0A//                properties.setProperty(%22hibernate.format_sql%22, %22true%22);%0A                /* properties.setProperty(%22hibernate.use_sql_comments%22, %22true%22); */%0A%0A
                 

Change to use Postgresql