import tango.io.Stdout;

void main()
	{

	Backbone theBackbone = new Backbone();
	TestClass der = new TestClass;
	theBackbone.registerEventHandler( "test_EVENT", &der.test );
	bool bla = false;
	byte[char[]][] derp;
	theBackbone.throwEvent( "test_EVENT", "void_main", derp );
	}
	
	class TestClass
	{
		public:
		int test( Event event) { Stdout("42424242424242"); return 42; }
	}
	
	
class Backbone {
	
private:
	HandlerLink* firstLink;
	HandlerLink* lastLink;
	HandlerLink* currentLink;
	
public:

	this()
	{
		HandlerLink hl = new HandlerLink( "", null, null, null );
		firstLink = &hl;
		//hl = new HandlerLink( "", null, null, null );
		//lastLink = &hl;
	}
	
	bool registerEventHandler( char[] event_id, int delegate(Event) fp ) {
	currentLink = firstLink.getNext();
		if( (currentLink is null))
		{
			HandlerLink hl = new HandlerLink( event_id, fp, null, null );
			hl.setNext( &hl );
			firstLink = &hl;
			lastLink = firstLink;
			
		} else {
			HandlerLink hl = new HandlerLink( event_id, fp, lastLink, null );
			lastLink.setNext( &hl );
			lastLink = &hl;
		}
		
		return true;
	}
	
	bool throwEvent( char[] event_id, char[] source, byte[char[]][] data)
	{
		
		Event evt = new Event( event_id, source, data );
		currentLink = firstLink;
		
		while( currentLink.getNext() !is null )
		{
			currentLink.processEvent( evt );
			currentLink = currentLink.getNext();
		}
		
		
		return true;
	}
	
	
	
}

class HandlerLink {
private:
	HandlerLink* nextHandlerLink;
	HandlerLink* previousHandlerLink;
	
	char[] event_id;
	
	int delegate(Event) functionToCall;
	
public:
	
	this(char[] event_id, int delegate(Event) dg, HandlerLink* previous, HandlerLink* next) {
		
		this.event_id = event_id;
		functionToCall = dg;
		
		previousHandlerLink = previous;
		nextHandlerLink = next;
		
	}
	
	HandlerLink* getPrevious()
	{
		return previousHandlerLink;
	}
	
	HandlerLink* getNext()
	{
		return nextHandlerLink;
	}
	
	bool setNext( HandlerLink* next )
	{
		nextHandlerLink = next;
		return true;
	}
	
	bool setPrevious( HandlerLink* previous )
	{
		previousHandlerLink = previous;
		return true;
	}
	
	bool processEvent( Event event )
	{
		if( this.event_id == event.getID() )
		{
			functionToCall( event );
			return true;
		}
		return false;
	}
	
}

class Event
{
private:
	char[] event_id;
	char[] source;
	byte[char[]][] eventData;
	
public:
	this(char[] event_id, char[] source, byte[char[]][] eventData)
	{
		this.event_id = event_id;
		this.source = source;
		this.eventData = eventData;
	}
	
	char[] getID()
	{
		return event_id;
	}
	
	char[] getSource()
	{
		return source;
	}
} 