package org.pandaa.test;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

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

import org.drools.compiler.kie.builder.impl.KieContainerImpl;
import org.drools.core.base.RuleNameEqualsAgendaFilter;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.Results;
import org.kie.api.runtime.Environment;
import org.kie.api.runtime.EnvironmentName;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.KieSessionConfiguration;

import com.codahale.metrics.MetricRegistry;

import bitronix.tm.BitronixTransactionManager;
import bitronix.tm.TransactionManagerServices;
import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.util.Duration;

public class Starter {
	
	private static KieServices ks;
	private static KieContainerImpl kContainer;
	private static Environment env;
	
	private static ScheduledExecutorService se = Executors.newScheduledThreadPool(10);
	
	private static List<String> ids = new ArrayList<>();
	
	private static DataSource ds;
	
	public static void main(String[] args) throws Exception {
		create();
//		load(4L);
	}
	
	
	public static void before() throws SQLException {
		boolean ms = false;
		if(ms) {
			
			DataSourceFactory factory = new DataSourceFactory();
			factory.setUrl("jdbc:sqlserver://ec2-52-50-120-144.eu-west-1.compute.amazonaws.com:1433;databaseName=surge_test");
			factory.setUser("artur");
			factory.setPassword("123456");
			factory.setValidationQuery("SELECT 1");
			factory.setMinSize(8);
			factory.setMaxSize(32);
			factory.setCheckConnectionWhileIdle(true);
			factory.setEvictionInterval(Duration.seconds(10));
			factory.setMinIdleTime(Duration.minutes(1));
			factory.setDriverClass("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			
			ds = factory.build(new MetricRegistry(), "test");
		} else {

			DataSourceFactory factory = new DataSourceFactory();
			factory.setUrl("jdbc:mysql://localhost:3306/drools");
			factory.setUser("root");
			factory.setPassword("");
			factory.setValidationQuery("SELECT 1");
			factory.setMinSize(8);
			factory.setMaxSize(32);
			factory.setCheckConnectionWhileIdle(true);
			factory.setEvictionInterval(Duration.seconds(10));
			factory.setMinIdleTime(Duration.minutes(1));
			factory.setDriverClass("com.mysql.jdbc.Driver");
			
			ds = factory.build(new MetricRegistry(), "test");
		}
	}
	
	
	private static void create() throws InterruptedException, SQLException {
		before();
		BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();

		Map<Object, Object> properties = new HashMap<>();
		properties.put(org.hibernate.cfg.Environment.DATASOURCE, ds);
		
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.jbpm.persistence.jpa", properties);
		
		ks = KieServices.Factory.get();
		kContainer = (KieContainerImpl) ks.getKieClasspathContainer();
		Results verify = kContainer.verify();
		if(verify.hasMessages(org.kie.api.builder.Message.Level.ERROR)) {
			throw new IllegalStateException("Could not build KIEBase:" + verify.toString());
		}
		
		env = ks.newEnvironment();
		env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
		env.set(EnvironmentName.TRANSACTION_MANAGER, tm);
		
		KieSessionConfiguration newKieSessionConfiguration = ks.newKieSessionConfiguration();
		
		KieBase kieBase = kContainer.getKieBase("base");
	
		final KieSession jpaSession = ks.getStoreServices().newKieSession(kieBase, newKieSessionConfiguration, env);
	
		Runtime.getRuntime().addShutdownHook(new Thread() {
			
			@Override
			public void run() {
				System.err.println("ID: " + jpaSession.getIdentifier());
				System.out.println("Count: " + jpaSession.getFactCount());
//				jpaSession.fireAllRules(new RuleNameEqualsAgendaFilter("expiry"));
				jpaSession.dispose();
			}
			
		});
		
		MyEvent e = new MyEvent();
		e.setUsers(get());

		TransactionHelper.inTransaction(() -> {
			jpaSession.insert(e);
		});
		
		jpaSession.fireAllRules();
		
		long now = System.currentTimeMillis();

		final long identifier = jpaSession.getIdentifier();
		
		System.err.println("Took: " + (System.currentTimeMillis() - now));
		System.err.println("Now change the main to call the loading with id: " + identifier);
		
		new Thread() { 
			
			public void run() {
				
				for(int i =0; i < 5; i++) {
					System.err.println("Start new run");
					
					final ExpiryFact fact = new ExpiryFact();
					fact.time = i;
					try {
						se.submit(() -> {
							try {
								jpaSession.insert(fact);
								int fireAllRules = jpaSession.fireAllRules(new RuleNameEqualsAgendaFilter("expiry"));
								System.out.println("Expiry run. Sleep for a while. Rules: " + fireAllRules);
							} catch (Exception e2) {
//								e2.printStackTrace();
								System.out.println("Error");
							}
						}).get();
					} catch (ExecutionException e1) {
						System.err.println("err");
						
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					try {
						System.out.println("Sleep");
						Thread.sleep(30000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
			};
			
		}.start();
		
		System.out.println("Fact count " + jpaSession.getFactCount());
		System.err.println("Now change the main to call the loading with id: " + identifier);
	}
	
	private static void load(final long identifier) throws SQLException {
		BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
		before();
		Map<Object, Object> properties = new HashMap<>();
		properties.put(org.hibernate.cfg.Environment.DATASOURCE, ds);
		
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.jbpm.persistence.jpa", properties);
		
		
		ks = KieServices.Factory.get();
		kContainer = (KieContainerImpl) ks.getKieClasspathContainer();
		KieSessionConfiguration newKieSessionConfiguration = ks.newKieSessionConfiguration();
		Results verify = kContainer.verify();
		if(verify.hasMessages(org.kie.api.builder.Message.Level.ERROR)) {
			throw new IllegalStateException("Could not build KIEBase:" + verify.toString());
		}
		
		env = ks.newEnvironment();
		env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
		env.set(EnvironmentName.TRANSACTION_MANAGER, tm);
		
		KieBase kieBase = kContainer.getKieBase("base");
	
		KieSession jpaSession = ks.getStoreServices().loadKieSession(identifier, kieBase, newKieSessionConfiguration, env);
		System.err.println("Count: " + jpaSession.getFactCount());
	}
	
	public static List<MyModel> get() {
		List<MyModel> res = new ArrayList<>();
		for(int i=0; i< 1000; i++) {
			MyModel m = new MyModel();
			m.asked = i % 10 + 1;
			String string = UUID.randomUUID().toString();
			ids.add(string);
			m.setName(string);
			res.add(m);
		}
		return res;
	}
	
}
