package com.sample;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.command.Command;
import org.drools.command.CommandFactory;
import org.drools.definition.KnowledgePackage;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;



public class PropertyListenerTest {

	public static void main(String[] args) {
		new PropertyListenerTest().runTest();
	}
	
	public void runTest() {
		StatefulKnowledgeSession session = startNewSession();
		
		ArrayList<Person> people = new ArrayList<Person>();
		people.add(new Person("Test 1"));
		people.add(new Person("Test 2"));
		
		printListeners(people, "== Listeners attached before rules ==");
		// call rules
		List<Command<?>> commands = new ArrayList<Command<?>>();
		commands.add(CommandFactory.newInsert(people));
		commands.add(CommandFactory.newFireAllRules());
		session.execute(CommandFactory.newBatchExecution(commands));
		session.dispose();
		System.out.println("Session disposed");
		printListeners(people, "== Listeners attached after rules ==");
		
		// update name to trigger update
		people.get(0).setName("Test 3");

	}
	
	private void printListeners(ArrayList<Person> people, String header) {
		System.out.println(header);
		for (Person person : people) {
			//System.out.println(" " + person);
			for (PropertyChangeListener listener : person.getBoundSupport().getPropertyChangeListeners()) {
				System.out.println("Listener attached of type: " + listener);
			}
		}
		System.out.println(header);
	}
	
	public static class Person {
		
		private String name;
		
		private PropertyChangeSupport boundSupport;
		
		public Person() {
			this(null);
		}
		
		public Person(String name) {
			this.name = name;
		}
		
	    public String getName() {
	        return name;
	    }

	    public void setName(String value) {
	        String oldValue = this.name;
	        this.name = value;
	        PropertyChangeSupport support = this.getBoundSupport();
	        support.firePropertyChange("name", oldValue, this.name);
	    }

	    public PropertyChangeSupport getBoundSupport() {
	        if (null == this.boundSupport) {
	            this.boundSupport = new PropertyChangeSupport(this);
	        }
	        return this.boundSupport;
	    }
	    
	    public void removePropertyChangeListener(String param0, PropertyChangeListener param1) {
	        this.getBoundSupport().removePropertyChangeListener(param0, param1);
	    }

	    public void addPropertyChangeListener(String param0, PropertyChangeListener param1) {
	        this.getBoundSupport().addPropertyChangeListener(param0, param1);
	    }

	    public void removePropertyChangeListener(PropertyChangeListener param0) {
	        this.getBoundSupport().removePropertyChangeListener(param0);
	    }

	    public void addPropertyChangeListener(PropertyChangeListener param0) {
	        this.getBoundSupport().addPropertyChangeListener(param0);
	    }
	    
	}
	
	private static KnowledgeBase kbase;
	
	private StatefulKnowledgeSession startNewSession() {
		if (kbase == null) {
			loadRules();
		}
		return kbase.newStatefulKnowledgeSession();
	}

	private void loadRules() {
		kbase = KnowledgeBaseFactory.newKnowledgeBase();
		KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
		kbuilder.add(ResourceFactory.newClassPathResource("PropertyListenerTest.drl"), ResourceType.DRL);
		Collection<KnowledgePackage> knowledgePackages = kbuilder.getKnowledgePackages();
		KnowledgeBuilderErrors errors = kbuilder.getErrors();
		if (errors.size() > 0) {
			for (KnowledgeBuilderError error: errors) {
				throw new RuntimeException(error.getMessage());
			}
		}
		kbase.addKnowledgePackages(knowledgePackages);
	}
}
