/**
 * Rivet Software Inc.
 * ©Copyright 2006-2009 Rivet Software, Inc. All rights reserved.
 **/

if( !HD ){
	var HD = {};
}

HD.Event = function(node, event, callback, data){
	if( arguments.length ){
		event = event.toLowerCase();
		if (event.substring(0, 2) == 'on') {
			event = event.substring(2, event.length);
		}
		
		var me = this;
		this.Callback = function(e){
			if (!e) 
				e = window.event;
			me.Extend(e);
			return callback(me);
		}
		
		this.Data = data;
		this.Node = node;
		this.Type = event;
	}
}

HD.Event.prototype.Attach = function(){
	if( this.Node.attachEvent ){
		this.Node.attachEvent( 'on'+ this.Type, this.Callback );
	}else{
		this.Node.addEventListener( this.Type, this.Callback, false );
	}
}

HD.Event.prototype.Detach = function(){
	if( this.Node.detachEvent ){
		this.Node.detachEvent( 'on'+ this.Type, this.Callback );
	}else{
		this.Node.removeEventListener( this.Type, this.Callback, false );
	}
}

HD.Event.prototype.Extend = function( e ){
	this.Event = e;
	this.Point = this.GetPoint();
	this.Target = this.GetTarget();
}

HD.Event.prototype.GetPoint = function(){
	var point = {};
	if( document.all ){
		point.X = this.Event.clientX;
		point.Y = this.Event.clientY;
	}else{
		point.X = this.Event.pageX;
		point.Y = this.Event.pageY;
	}

	return point;
}

HD.Event.prototype.GetTarget = function(){
	if( this.Event.srcElement ){
		return this.Event.srcElement;
	}else if( this.Event.originalTarget ){
		return this.Event.originalTarget;
	}
}

HD.OnLoad = function( callback ){
	//If called by the actual window.onload event
	if( isTypeOf( callback, HD.Event ) ){
		HD.OnLoad( true );
	}else if( callback === true ){
		if( this.Callbacks ){
			while( this.Callbacks.length ){
				this.Callbacks.shift()();
			}
		}

		this.Loaded = true;
	}else if( this.Loaded ){
		//If the page has loaded, just run the method
		callback();
	}else{
		if( !this.Callbacks ){
			this.Callbacks = [];
		}

		//If the page has not loaded, add it to the queue
		this.Callbacks.push( callback );
	}
}

//Set up the load listener
var e = new HD.Event( window, 'load', objectiveReference( HD.OnLoad ) );
	e.Attach();

HD.Event.OnClick = function( node, method, data ){
	var e = new HD.Event( node, 'click', method, data );
		e.Attach();

	return e; 
}

HD.Event.OnDoubleClick = function( node, method, data ){
	var e = new HD.Event( node, 'dblclick', method, data );
		e.Attach();
	
	return e; 
}

HD.Event.OnKeyDown = function( node, method, data ){
	var e = new HD.Event( node, 'keydown', method, data );
		e.Attach();
	
	return e; 
}

HD.Event.OnKeyPress = function( node, method, data ){
	var e = new HD.Event( node, 'keypress', method, data );
		e.Attach();
	
	return e; 
}

HD.Event.OnKeyUp = function( node, method, data ){
	var e = new HD.Event( node, 'keyup', method, data );
		e.Attach();
	
	return e; 
}

HD.Event.OnMouseDown = function( node, method, data ){
	var e = new HD.Event( node, 'mousedown', method, data );
		e.Attach();
	
	return e; 
}

HD.Event.OnMouseMove = function( node, method, data ){
	var e = new HD.Event( node, 'mousemove', method, data );
		e.Attach();
	
	return e; 
}

HD.Event.OnMouseOut = function( node, method, data ){
	var e = new HD.Event( node, 'mouseout', method, data );
		e.Attach();
	
	return e; 
}

HD.Event.OnMouseOver = function( node, method, data ){
	var e = new HD.Event( node, 'mouseover', method, data );
		e.Attach();
	
	return e; 
}

HD.Event.OnMouseUp = function( node, method, data ){
	var e = new HD.Event( node, 'mouseup', method, data );
		e.Attach();
	
	return e; 
}

if( HD.Element ){
HD.Element.prototype.OnClick = function( method, data ){
	return new HD.Event( this, 'click', method, data );
}

HD.Element.prototype.OnDoubleClick = function( method, data ){
	return HD.Event( this, 'dblclick', method, data );
}

HD.Element.prototype.OnKeyDown = function( method, data ){
	return HD.Event( this, 'keydown', method, data ); 
}

HD.Element.prototype.OnKeyPress = function( method, data ){
	return HD.Event( this, 'keypress', method, data );
}

HD.Element.prototype.OnKeyUp = function( method, data ){
	return onKeyUp( this, 'keyup', method, data );
}

HD.Element.prototype.OnMouseDown = function( method, data ){
	return HD.Event( this, 'mousedown', method, data );
}

HD.Element.prototype.OnMouseMove = function( method, data ){
	return HD.Event( this, 'mousemove', method, data );
}

HD.Element.prototype.OnMouseOut = function( method, data ){
	return HD.Event( this, 'mouseout', method, data );
}

HD.Element.prototype.OnMouseOver = function( method, data ){
	return HD.Event( this, 'mouseover', method, data );
}

HD.Element.prototype.OnMouseUp = function( method, data ){
	return HD.Event( this, 'mouseup', method, data );
}
}

if( !HD.State ){
	HD.State = {};
}

if( !HD.State.Loaded ){
	HD.State.Loaded = {};
}

HD.State.Loaded.Event = true;

function isObjective( obj ){
	return obj != null && isTypeOf( obj, Object );
}

function isString(val) {
	try{
		return val.toString() === val;
	}catch( fail ){
		return false;
	}
}

function isTypeOf(obj, cls) {
	return obj instanceof cls;
}

function objectiveReference() {
	args = toArray(arguments);
	var method = args.shift();
	var object = args.shift();

	return function() {
		return method.apply(object, arguments || args);
	}
}

function toArray( list ){
	var array = [];
	if (!isString(list)) {
		for (var i = 0; i < list.length; i++) {
			array.push(list[i]);
		}
	}
	return array;
}