package com.ibtp.kontor.dal;

import org.hibernate.jpa.HibernatePersistenceProvider;
import org.hsqldb.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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;

/**
 * Created by TPEETZ on 19.01.2015.
 */
public class LocalDatabase implements Database {

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

    private LocalDatabase() {
        logger.info("LocalDatabase started");
    }

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

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

    private static void stopDatabase() {
        server.shutdown();
    }
    private static EntityManagerFactory getFactory() {
        if (LocalDatabase.factory == null) {
            LocalDatabase.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_;
                }
            });
            LocalDatabase.factory = Persistence.createEntityManagerFactory("com.ibtp.kontor");
            logger.info("EntityManagerFactory(com.ibtp.kontor) created");
        }
        return LocalDatabase.factory;
    }

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

    private static void setSingleEntityManager(EntityManager manager) {
        LocalDatabase.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 (LocalDatabase.server == null) {
            serverMessage = "server:null";
        } else {
            serverMessage = LocalDatabase.server.toString();
        }
        return LocalDatabase.class.getName() + " " + serverMessage;
    }
}
