package info.elexis.server.core.connector.elexis.internal;

import static org.eclipse.persistence.config.PersistenceUnitProperties.*;

import java.util.HashMap;
import java.util.Optional;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.criteria.CriteriaBuilder;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.jpa.EntityManagerFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import info.elexis.server.core.connector.elexis.common.DBConnection;
import info.elexis.server.core.connector.elexis.common.ElexisDBConnection;
import info.elexis.server.core.connector.elexis.jpa.ProvidedEntityManager;

@Component
public class ElexisEntityManager {

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

	private static EntityManagerFactoryBuilder factoryBuilder;
	private static EntityManagerFactory factory;

	@Reference(
			service = EntityManagerFactoryBuilder.class, 
			cardinality = ReferenceCardinality.MANDATORY, 
			policy = ReferencePolicy.STATIC, 
			unbind = "deactivate",
			target = "(osgi.unit.name=elexis)")
	protected synchronized void activate(EntityManagerFactoryBuilder factoryBuilder) {
		ElexisEntityManager.factoryBuilder = factoryBuilder;
		ElexisEntityManager.initializeEntityManager();
	}

	public static void initializeEntityManager() {
		Optional<DBConnection> connection = ElexisDBConnection.getConnection();
		if(!connection.isPresent()) {
			log.error("No elexis-connection available, not initialization EntityManager");
			return;
		}	
		
		HashMap<String, Object> props = new HashMap<String, Object>();
		try {
			props.put(JDBC_DRIVER, connection.get().rdbmsType.driverName);
			props.put(JDBC_URL, connection.get().connectionString);
			props.put(JDBC_USER, connection.get().username);
			props.put(JDBC_PASSWORD, connection.get().password);
			props.put(DDL_GENERATION, NONE);
			if (ElexisDBConnection.isTestMode()) {
				// we don't want the entities to generate the database, as
				// initialization is handled via the creation scripts
				props.put("eclipselink.ddl-generation", "none");
				props.put("eclipselink.ddl-generation.output-mode", "database");
			}

			factory = ElexisEntityManager.factoryBuilder.createEntityManagerFactory(props);
			// TODO refactor this
			ProvidedEntityManager.setEntityManagerFactory(factory);
		} catch (RuntimeException ite) {
			log.error("Error activating component", ite);
			ite.printStackTrace();
		}
	}

	protected synchronized void deactivate(EntityManagerFactoryBuilder factoryBuilder) {
		ElexisEntityManager.factoryBuilder = null;
	}
	
	public static CriteriaBuilder getCriteriaBuilder() {
		return factory.getCriteriaBuilder();
	}

	public static EntityManager createEntityManager() {
		return factory.createEntityManager();
	}
}

@@ -1149,20 +1149,16 @@
 ference(
-%0A%09%09%09
 service 
@@ -1194,20 +1194,16 @@
 .class, 
-%0A%09%09%09
 cardinal
@@ -1240,20 +1240,16 @@
 DATORY, 
-%0A%09%09%09
 policy =
@@ -1273,20 +1273,16 @@
 STATIC, 
-%0A%09%09%09
 unbind =
@@ -1295,20 +1295,17 @@
 tivate%22,
-%0A%09%09%09
+ 
 target =
@@ -1650,16 +1650,17 @@
 ();%0A%09%09if
+ 
 (!connec
@@ -1775,20 +1775,17 @@
 urn;%0A%09%09%7D
-%09%0A%09%09
+%0A
 %0A%09%09HashM
@@ -2829,17 +2829,16 @@
 ull;%0A%09%7D%0A
-%09
 %0A%09public
@@ -2880,24 +2880,50 @@
 Builder() %7B%0A
+%09%09if (factory != null) %7B%0A%09
 %09%09return fac
@@ -2945,24 +2945,222 @@
 aBuilder();%0A
+%09%09%7D else %7B%0A%09%09%09System.out.println(%22Trying to create CriteriaBuilder on null EntityManagerFactory%22);%0A%09%09%09log.error(%22Trying to create CriteriaBuilder on null EntityManagerFactory%22);%0A%09%09%7D%0A%09%09return null;%0A%0A
 %09%7D%0A%0A%09public 
@@ -3204,16 +3204,42 @@
 ger() %7B%0A
+%09%09if (factory != null) %7B%0A%09
 %09%09return
@@ -3270,13 +3270,206 @@
 ager();%0A
+%09%09%7D else %7B%0A%09%09%09System.out.println(%22Trying to create EntityManager on null EntityManagerFactory%22);%0A%09%09%09log.error(%22Trying to create EntityManager on null EntityManagerFactory%22);%0A%09%09%7D%0A%09%09return null;%0A
 %09%7D%0A%7D%0A

Identify possible NPE in ElexisEntityManager