package org.test;

import java.util.ArrayList;
import java.util.List;

import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.Message.Level;
import org.kie.api.definition.rule.Rule;
import org.kie.api.event.rule.ObjectDeletedEvent;
import org.kie.api.event.rule.ObjectInsertedEvent;
import org.kie.api.event.rule.ObjectUpdatedEvent;
import org.kie.api.event.rule.WorkingMemoryEventListener;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class ProximityTest {

	private void CreateKieRuleOnTheFly() {

		KieServices ks = KieServices.Factory.get();
		KieRepository kr = ks.getRepository();
		KieFileSystem kfs = ks.newKieFileSystem();

		// Can't understand why this does not work without the
		// src/main/resources part
		kfs.write("src/main/resources/org/test/rule.drl", getRule());
		KieBuilder kb = ks.newKieBuilder(kfs);
		kb.buildAll(); 
		if (kb.getResults().hasMessages(Level.ERROR)) {
			throw new RuntimeException("Build Errors:\n"
					+ kb.getResults().toString());
		}
		KieContainer kContainer = ks.newKieContainer(kr.getDefaultReleaseId());
		KieSession kSession = kContainer.newKieSession();
		kSession.addEventListener(new WorkingMemoryEventListener() {
			@Override
			public void objectUpdated(ObjectUpdatedEvent oue) {
				System.out.println("objectUpdated " + oue.getObject());
			}

			@Override
			public void objectInserted(ObjectInsertedEvent oi) {
				System.out.println("objectInserted " + oi.getObject());
			}

			@Override
			public void objectDeleted(ObjectDeletedEvent ore) {
				System.out.println("objectRetracted " + ore.getOldObject());
			}
		});

		// CloseTrack closeTrack = new CloseTrack(100,200);
		Track track = new Track(100);
		// track.getCloseTracks().add(closeTrack);
		// kSession.insert(track);
		// track = new Track(200);
		kSession.insert(track);

		kSession.fireAllRules();

		KieBase kieBase = kSession.getKieBase();
		Rule rule = kieBase.getRule("org.test", "ProxRule");
		System.out.println(rule);
		kieBase.removeRule("org.test", "ProxRule");

		System.out.println("done");
	}

	private static String getRule() {
		String s = ""
				+ "package org.test"
				+ "\nimport org.test.ProximityTest.*"
				+ "\nrule \"ProxRule\""
				+ "\nwhen "
				+ "\n	$track:Track("
				+ "\n	)"
				+ "\n	$track1:Track("
				+ "\n	)"
				+ "\n		exists (CloseTrack(closeTrackId==$track1.trackId) from $track.closeTracks)"
				+ "\nthen " + "\nSystem.out.println(\"proximity asserted\"); "
				+ "\nend";
		return s;
	}

	/** test main */
	public static void main(String[] args) {
		(new ProximityTest()).CreateKieRuleOnTheFly();
	}

	public class CloseTrack {

		private int trackId;
		private int closeTrackId;

		public CloseTrack(int i, int j) {
			this.trackId = i;
			this.closeTrackId = j;
		}

		public int getTrackId() {
			return trackId;
		}

		public void setTrackId(int trackId) {
			this.trackId = trackId;
		}

		public int getCloseTrackId() {
			return closeTrackId;
		}

		public void setCloseTrackId(int closeTrackId) {
			this.closeTrackId = closeTrackId;
		}
	}

	public class Track {

		private int trackId;
		private List<CloseTrack> closeTracks = new ArrayList<CloseTrack>();

		public Track(int i) {
			this.trackId = i;
		}

		public List<CloseTrack> getCloseTracks() {
			return closeTracks;
		}

		public int getTrackId() {
			return trackId;
		}

		public void setTrackId(int id) {
			this.trackId = id;
		}

		public void setCloseTracks(List<CloseTrack> closeTracks) {
			this.closeTracks = closeTracks;
		}

	}
}
