/*****************************\
  GSSI Events framework
  Requires: Base, Environment
\*****************************/

if (! GSSI) { alert("gssi.events.js: gssi.base.js not loaded") };
if (! GSSI.Environment) { alert("gssi.events.js: gssi.environment.js not loaded") };
GSSI.Events = {};

GSSI.Events._iecache = [];

GSSI.Events.Add = function(element, name, handler, raw) {
	element = GSSI.$(element);
	if (element instanceof Array) {
		for (var i = 0; i < element.length; i++) { GSSI.Events.Add(element[i], name, handler, raw); };
		return;
	}
	name = GSSI.Events._eventname( name );
	if (! element.id) { element.id = name + GSSI.Base.UID(); }
	
	var h = raw ? handler : GSSI.Events._wraphandler(handler, element, name);
	
	if (element.addEventListener) {
		element.addEventListener(name, h, false);
	} else if (element.attachEvent) {
		element.attachEvent('on' + name, h);
	}
	GSSI.Events._iecache.push( { element:element, name:name, handler:handler } );
};

GSSI.Events.Remove = function(element, name, handler) {
	element = GSSI.$(element);
	if (element instanceof Array) {
		for (var i = 0; i < element.length; i++) { GSSI.Events.Remove(element[i], name, handler, raw); };
		return;
	}
	name = GSSI.Events._eventname( name );
	
	var h = GSSI.Events._gethandlerwrapper(handler, element, name);
	
	if (element.removeEventListener) {
		element.removeEventListener(name, h, false);
	} else if (element.detachEvent) {
		try {
			element.detachEvent('on' + name, h);
		} catch (e) {}
	};
};

GSSI.Events.onDOMReady = function ( f ) { GSSI.Environment.onDOMReady( f ); };

GSSI.Events._eventname = function( name ) {
	if (name.indexOf('on') === 0) { name = name.substr(2); }
    if (name == 'keypress' && GSSI.Environment.Browser.KHTML) { name = 'keydown'; };
	if ( (name == 'mousewheel') && document.body.addEventListener && (!window.opera)) {
		name = 'DOMMouseScroll';
	} else if ( (name == 'DOMMouseScroll') &&  document.body.attachEvent) {
		name = 'mousewheel';
	}
	return name;	
};

GSSI.Events._standardize = function( event ) {
	var e = (event) ? GSSI.Base.Clone(event) : GSSI.Base.Clone(window.event);
	e.target = e.target || e.srcElement;
	if ((e.target) && (e.target.nodeType == 3)) { e.target = e.target.parentNode; };  // 3 = textNode.
	if ((e.button !== undefined) && (e.button !== null)) { // button value is a mess, but is set only for mouse events
		if (e.which && (! GSSI.Environment.Browser.KHTML) ) {
			e.leftbutton = (e.which == 1);
			e.middlebutton = (e.which == 2);
			e.rightbutton = (e.which == 3);
		} else {
			e.leftbutton = (e.button & 1) == 1;
			e.middlebutton = (e.button & 4) == 4;
			e.rightbutton = (e.button & 2) == 2;
		}
	};
	e.rightbutton = ( ((e.button & 2) == 2) || (e.which==2) );
	e.leftbutton = (((e.which) && (e.which == 1)) || (e.button === 1));
	e.middlebutton = (e.which || e.button)
	if ((e.pageX === undefined) || (e.pageX === null)) {
		e.pageX = e.clientX + document.body.scrollLeft	+ document.documentElement.scrollLeft;
		e.pageY = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
	}
	var wd = 0;
	if (e.wheelDelta) {
		wd = e.wheelDelta * ( window.opera ? 1 : -1 );
	} else {
		wd = e.detail || 0;
	}
	e.wheeldirection = ( (wd<0) ? (-1) : ( (wd>0)? 1: 0 ) );

	e.relatedTarget = e.relatedTarget || ( (e.fromElement==e.target) ? e.toElement : e.fromElement );
	return e;
};

GSSI.Events._wraphandler = function( basehandler, element, name ) {
	var evid = element.id + " " + name;
	if ( basehandler._gssihandlers && basehandler._gssihandlers[evid] ) { return basehandler._gssihandlers[element.id]; }
	basehandler._gssihandlers = basehandler._gssihandlers || {};
	basehandler._gssihandlers[evid] = function(e) { return basehandler.apply(element, [GSSI.Events._standardize(e)]); }
	return basehandler._gssihandlers[evid];
};

GSSI.Events._gethandlerwrapper = function( basehandler, element, name ) {
	if (! basehandler._gssihandlers) { return basehandler; }
	return basehandler._gssihandlers[element.id + " " + name] || basehandler;
};

GSSI.Events._mousepositionwatcher = function(e){
	if (!e) { var e = window.event; }
	if ((e.pageX === undefined) || (e.pageX === null)) {
		try {
			GSSI.Events.Mouse.x = e.clientX + document.body.scrollLeft	+ document.documentElement.scrollLeft;
			GSSI.Events.Mouse.y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
		} catch(e) {};
	} else {
		GSSI.Events.Mouse.x = e.pageX;
		GSSI.Events.Mouse.y = e.pageY;
	}
};

GSSI.Events._mousedownwatcher = function(e){
	if (!e) { var e = window.event; }
	if (e.which && (! GSSI.Environment.Browser.KHTML) ) {
		if (e.which == 1) { GSSI.Events.Mouse.leftbutton = true; };
		if (e.which == 2) { GSSI.Events.Mouse.middlebutton = true; };
		if (e.which == 3) { GSSI.Events.Mouse.rightbutton = true; };
	} else {
		if ((e.button & 1) == 1) { GSSI.Events.Mouse.leftbutton = true; }
		if ((e.button & 4) == 4) { GSSI.Events.Mouse.middlebutton = true; };
		if ((e.button & 2) == 2) { GSSI.Events.Mouse.rightbutton = true; };
	}
};

GSSI.Events._mouseupwatcher = function(e){
	if (!e) { var e = window.event; }
	if (e.which && (! GSSI.Environment.Browser.KHTML) ) {
		if (e.which == 1) { GSSI.Events.Mouse.leftbutton = false; };
		if (e.which == 2) { GSSI.Events.Mouse.middlebutton = false; };
		if (e.which == 3) { GSSI.Events.Mouse.rightbutton = false; };
	} else {
		if ((e.button & 1) == 1) { GSSI.Events.Mouse.leftbutton = false; }
		if ((e.button & 4) == 4) { GSSI.Events.Mouse.middlebutton = false; };
		if ((e.button & 2) == 2) { GSSI.Events.Mouse.rightbutton = false; };
	}
};

GSSI.Events.WatchMouse = function( go ) {	
	if (go === false) {
		GSSI.Events.Remove( document, 'mousemove', GSSI.Events._mousepositionwatcher );
		GSSI.Events.Remove( document, 'mousedown', GSSI.Events._mousedownwatcher );
		GSSI.Events.Remove( document, 'mouseup', GSSI.Events._mouseupwatcher );
		GSSI.Events.Mouse = null;
	} else {
		if (! GSSI.Events.Mouse) {
			GSSI.Events.Mouse = {};
			GSSI.Events.Add( document, 'mousemove', GSSI.Events._mousepositionwatcher, true );
			GSSI.Events.Add( document, 'mousedown', GSSI.Events._mousedownwatcher, true );
			GSSI.Events.Add( document, 'mouseup', GSSI.Events._mouseupwatcher, true );
		}
	};
}

if( GSSI.Environment.Browser.IE ) {
	GSSI.Events.Add( window, "unload", function() {
		var l, ev;
		l = GSSI.Events._iecache.length;
		for( var i=0; i<l; i++ ) {
			ev = GSSI.Events._iecache[i];
			GSSI.Events.Remove( ev.element, ev.name, ev.handler );
		}
		GSSI.Events._iecache = [];
	});
};

GSSI.Base.Extend( GSSI.ElementPrototype,  {
	addEvent: function( name, handler, raw ) {
		GSSI.Events.Add( this, name, handler, raw );
	},
	removeEvent: function( name, handler ) {
		GSSI.Events.Remove( this, name, handler );
	}
});


