package com.ibtp.kontor.util;

import com.ibtp.kontor.dal.Database;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.hsqldb.Server;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceProviderResolver;
import javax.persistence.spi.PersistenceProviderResolverHolder;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by TPEETZ on 21.01.2015.
 */
public class LocalTestDatabase implements Database {

    private static Server server;
    private static EntityManagerFactory factory;
    private static EntityManager em;
    private static Logger logger = LoggerFactory.getLogger(LocalTestDatabase.class.getName());

    static {
        logger.info("initialization and starting database");
        LocalTestDatabase.assureDatabaseRunning();
    }

    public LocalTestDatabase() {
        logger.info("LocalDatabaseTest started");
    }

    private static void assureDatabaseRunning() {
        if (LocalTestDatabase.server == null) {
            LocalTestDatabase.startDatabase();
        }
    }

    private static void startDatabase() {
        logger.info("startDatabase as kontor in hsqldb_databases/test");
        LocalTestDatabase.server = new Server();
        LocalTestDatabase.server.setAddress("localhost");
        LocalTestDatabase.server.setDatabaseName(0, "kontor");
        LocalTestDatabase.server.setDatabasePath(0, "file:build/hsqldb_databases/test");
        LocalTestDatabase.server.setPort(2345);
        LocalTestDatabase.server.setTrace(true);
        LocalTestDatabase.server.setLogWriter(new PrintWriter(System.out));
        LocalTestDatabase.server.start();
    }

    private static void stopDatabase() {
        server.shutdown();
    }

    private static EntityManagerFactory getFactory() {
        if (LocalTestDatabase.factory == null) {
            LocalTestDatabase.assureDatabaseRunning();
            PersistenceProviderResolverHolder.setPersistenceProviderResolver(new PersistenceProviderResolver() {
                private final List<PersistenceProvider> providers_ = Arrays.asList((PersistenceProvider) new HibernatePersistenceProvider());

                @Override
                public void clearCachedProviders() {
                    // Auto-generated method stub
                }

                @Override
                public List<PersistenceProvider> getPersistenceProviders() {
                    return providers_;
                }
            });
            LocalTestDatabase.factory = Persistence.createEntityManagerFactory("com.ibtp.kontor");
            logger.info("EntityManagerFactory(com.ibtp.kontor) created");
        }
        return factory;
    }

    private static EntityManager getSingleEntityManager() {
        return LocalTestDatabase.em;
    }

    private static void setSingleEntityManager(EntityManager manager) {
        LocalTestDatabase.em = manager;
    }

    @Override
    public EntityManager getEntityManager() {
        if (getSingleEntityManager() == null) {
            setSingleEntityManager(getFactory().createEntityManager());
            logger.info("EntityManager created");
        }
        return getSingleEntityManager();
    }

    @Override
    public String toString() {
        String serverMessage;
        if (LocalTestDatabase.server == null) {
            serverMessage = "server:null";
        } else {
            serverMessage = LocalTestDatabase.server.toString();
        }
        return LocalTestDatabase.class.getName() + " " + serverMessage;
    }
}
