package com.sample;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseConfiguration;
import org.drools.KnowledgeBaseFactory;
import org.drools.agent.KnowledgeAgent;
import org.drools.agent.KnowledgeAgentConfiguration;
import org.drools.agent.KnowledgeAgentFactory;
import org.drools.agent.impl.PrintStreamSystemEventListener;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderConfiguration;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.conf.EventProcessingOption;
import org.drools.core.util.FileManager;
import org.drools.io.Resource;
import org.drools.io.ResourceChangeScannerConfiguration;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.StatefulKnowledgeSession;
import org.junit.Before;
import org.junit.Test;


/**
 * Test case for 
 */
public class LoopTest {

	FileManager fileManager;
	KnowledgeBase kbase;

	@Before
	@SuppressWarnings("restriction")
	public void setUp() throws Exception {
		fileManager = new FileManager();
		fileManager.setUp();

		// creating initial rule
		System.out.println("FileManager path" + fileManager.getRootDirectory().getPath());
		fileManager.write("rule1.drl", createRule("b.getTiempo()",true));
		//fileManager.write("rule1.drl", createRule(" b.getTag()",false));

	}

	@Test
	@SuppressWarnings("restriction")
	public void testIncrementalKbaseChangesWithTemporalRules() throws Exception {


		KnowledgeBuilderConfiguration kbc = KnowledgeBuilderFactory	.newKnowledgeBuilderConfiguration();
		KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
		config.setOption(EventProcessingOption.STREAM);
		
		KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(kbc);
		KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(config);
		ResourceChangeScannerConfiguration sconf = ResourceFactory	.getResourceChangeScannerService().newResourceChangeScannerConfiguration();
		sconf.setProperty("drools.resource.scanner.interval", "2");
		ResourceFactory.getResourceChangeScannerService().configure(sconf);
		KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();

		aconf.setProperty("drools.agent.newInstance", "false");

		KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent("test agent", kbase, aconf, kbc);
		File changeset = createChangeSet();
		kagent.applyChangeSet(ResourceFactory.newUrlResource(changeset.toURI().toURL()));
		ResourceFactory.getResourceChangeNotifierService().start();
		ResourceFactory.getResourceChangeScannerService().start();

		StatefulKnowledgeSession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
		KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");

		UpdateKB updateKB= new UpdateKB ();


		String a1 = new String();
		AT alarm ;
		boolean carga=false; 


		System.out.println("after filling ");
		Now n;
		updateKB.start();
		for (int i=0;i<9000;i++) {
			System.out.println("--------------------------cycle"+i);
			alarm = new AT();
			alarm.setTag(a1.format("%d", i));
			alarm.setTiempo(new Date());
			ksession.insert(alarm);
			n=new Now();
			n.setTiempo(new Date());
			ksession.insert(n);
			try {
				
				ksession.fireAllRules();
				
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			System.out.println("**********  Completed ********");

		}
		logger.close();
	}

	@SuppressWarnings("restriction")
	public File createChangeSet() throws Exception {
		
		System.out.println("FileManager path" + fileManager.getRootDirectory().getPath());
		
		String xml = "";
		xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
		xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
		xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
		xml += "    <add> ";
		xml += "        <resource source='file:"+ fileManager.getRootDirectory().getPath()+ "/rule1.drl' type='DRL' />";
		xml += "    </add> ";
		xml += "</change-set>";

		return fileManager.write("changeset.xml", xml);
	}
	
	
    private static KnowledgeBase readKnowledgeBase() throws Exception {
		KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
		config.setOption(EventProcessingOption.STREAM);    	
    	
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newClassPathResource("Sample2.drl"), ResourceType.DRL);
        KnowledgeBuilderErrors errors = kbuilder.getErrors();
        if (errors.size() > 0) {
            for (KnowledgeBuilderError error: errors) {
                System.err.println(error);
            }
            throw new IllegalArgumentException("Could not parse knowledge.");
        }
        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(config);
        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
        return kbase;
    }



	public static class AT{
		private String tag;
		static Date to;
		public static Date getTiempo() {
			return to;
		}
		public  Date tiempo() {
			return to;
		}   
		/**
		 * @param tiempo
		 */
		public void setTiempo(Date tiempo) {
			AT.to = tiempo;
		}
		public String getTag() {
			return tag;
		}
		public void setTag(String tag) {
			this.tag = tag;
		}
		public int getTipo()
		{
			return 4;
		}
	}
	public static class Now{
		static Date to;
		public static Date getTiempo() {
			return to;
		}
		public  Date tiempo() {
			return to;
		}   
		public void setTiempo(Date tiempo) {
			AT.to = tiempo;
		}
	}

	public String createRule(String rhsMessage,boolean firstTime) {
		StringBuilder sb = new StringBuilder();

		sb.append("\n\npackage com.sample\n");
		sb.append("import java.util.List;\n");
		sb.append("import java.util.ArrayList;\n");
		sb.append("import java.util.Date;\n");


		sb.append("declare com.sample.LoopTest.AT\n");
		sb.append("@role(event)\n");
		sb.append("@expires(10000s)\n");
		sb.append("end\n");


		sb.append("declare com.sample.LoopTest.Now\n");
		sb.append("@role(event)\n");
		sb.append("@expires(1s)\n");
		sb.append("end\n");

		if(!firstTime)
		{
			sb.append("rule '1'\n");
			sb.append("dialect 'java'\n");
			sb.append("lock-on-active true\n");
			sb.append("no-loop true\n");


			sb.append("when\n");
			sb.append("b:com.sample.LoopTest.AT() over window:time(20s)\n");
			//sb.append("t:Now()\n");
			//sb.append("b:com.sample.LoopTest.AT(this before[100s] t) over window:time(2000s)\n"); 

			sb.append("then\n");
			sb.append("System.out.println(\"Rule1 \"+ "+rhsMessage+");\n");
			sb.append("end\n\n");


			sb.append("rule '2'\n");
			sb.append("dialect 'java'\n");
			sb.append("lock-on-active true\n");
			sb.append("no-loop true\n");
			sb.append("when\n");
			sb.append("b:com.sample.LoopTest.AT() over window:time(2000s)\n"); 

			sb.append("then\n");
			sb.append("System.out.println(\"Rule2 \" + "+rhsMessage+");\n");
			sb.append("end\n\n");

		}
		System.out.println(sb.toString());

		return sb.toString();
	}


	class UpdateKB extends Thread {

		UpdateKB() {

		}

		public void run() {
			int i=0;
			while(true)
			{
				try {
					i++;
					fileManager.write("rule1.drl", createRule(" b.getTag()",false));
					System.out.println(" ----------- Rule Definition Updated -------------");
					Thread.sleep(10000);
				} catch (Exception e) {

					e.printStackTrace();
				}
			}
		}
	}

}
