var DHTML = new function() {

	this.ie = (navigator.userAgent.toLowerCase().indexOf('msie') > -1);
	this.ie6 = (navigator.userAgent.toLowerCase().indexOf('msie 6') > -1);
	this.ie7 = (navigator.userAgent.toLowerCase().indexOf('msie 7') > -1);

	this.get = this.bind = function(e) { 
		if (!e) return null;
		if (!(e = DOM.get(e))) return null;

		OO.apply(e, this.Base);
		
		for (var superClass,index = 1;(superClass = arguments[index]);index++) {
			e.inherit(superClass);
		}
		
		e.ooInitSelf(e);
		return e;
	}

	this.create = function(type) {
		var e = document.createElement(type);
		if (!e) return null;
		
		OO.apply(e, this.Base);
		
		for (var superClass,index = 1;(superClass = arguments[index]);index++) {
			e.inherit(superClass);
		}
		
		e.ooInitSelf.apply(e);
		return e;
	}
	
	this._path = function(start, end, time) {
		var time = Math.ceil(time / 25);
		var period = Math.PI / (2 * time);
		var result = [];
		end -= start;
		for (var index = 0; index <= time; index++) { result.push(Math.round(end * Math.sin(period * index) + start)); }
		return result;
	}

	this._path = function(start, end, time) {
		var time = Math.ceil(time / 25);
		var period = Math.PI / (2 * time);
		var result = [];
		end -= start;
		for (var index = 0; index <= time; index++) { result.push(Math.round(end * Math.sin(period * index) + start)); }
		return result;
	}
	
	this.clientHeight = function() {
		return document.body.clientHeight || window.innerHeight;
	}
	
	this.clientWidth = function() {
		return document.body.clientWidth || window.innerWidth;
	}
	
	this.structure = function(e) {
		return this.get(DOM.structure(e));
	}

	var div = document.createElement('div');
	
	if (UTIL.def(div.style.pixelLeft)) { 
		this.setLeft = function(e, x) { e.style.right = ''; e.style.pixelLeft = x; };
		this.setRight = function(e, x) { e.style.left = ''; e.style.pixelRight = x; };
		this.setTop = function(e, y) { e.style.bottom = ''; e.style.pixelTop = y; };
		this.setBottom = function(e, y) { e.style.top = ''; e.style.pixelBottom = y; };
	} else if (UTIL.def(div.style.left)) {
		this.setLeft = function(e, x) { e.style.right = ''; e.style.left = x+'px'; };
		this.setRight = function(e, x) { e.style.left = ''; e.style.right = x+'px'; };
		this.setTop = function(e, y) { e.style.bottom = ''; e.style.top = y+'px'; };
		this.setBottom = function(e, y) { e.style.top = ''; e.style.bottom = y+'px'; };
	}
	
	this.divX = function(e, x) { res = e.offsetLeft - e.offsetParent.scrollLeft; if (UTIL.def(x)) DHTML.setLeft(e, x); return res;}
	this.divY = function(e, y) { res = e.offsetTop - e.offsetParent.scrollTop; if (UTIL.def(y)) DHTML.setTop(e, y); return res;}
		

	this.pageX = function(e) {
		var x = e.offsetLeft;
		while (e=e.offsetParent) x += (e.offsetLeft - e.scrollLeft);
		return x;
	}

	this.pageY = function(e) {
		var y = e.offsetTop;
		while (e=e.offsetParent) y += (e.offsetTop - e.scrollTop);
		return y;
	}
	
	this.getWidth = function(e) { return parseInt(e.offsetWidth, 10); }
	this.getHeight = function(e) { return parseInt(e.offsetHeight, 10); }
	this.setWidth = function(e, w) { e.style.width = w+'px'; }
	this.setHeight = function(e, h) { e.style.height = h+'px'; }

	this.show = function(e) { e.style.visibility = 'visible'; }
	this.hide = function(e) { e.style.visibility = 'hidden'; }
	this.display = function(e, d) { var r = e.style.display; if (U.def(d)) e.style.display = d; return r; }
	this.zIndex = function(e, z) { var r = parseInt(e.style.zIndex, 10); if (U.def(z)) e.style.zIndex = z; return r; },

	this.center = function(ele, h, v, e) {
		e = DOM.get(e) || ele.offsetParent;
		if (h) { this.setLeft(ele, Math.round((this.getWidth(e) - this.getWidth(ele)) / 2)); }
		if (v) { this.setTop(ele, Math.round((this.getHeight(e) - this.getHeight(ele)) / 2)); }
	}
	
	if (UTIL.def(div.style.filter)) {
		this.setOpacity = function(e, o) { e.style.filter = 'alpha(opacity='+o+')'; };
	} else if (UTIL.def(div.style.MozOpacity)) {
		this.setOpacity = function(e, o) { e.style.MozOpacity = Math.min(o / 100, 0.9999); };
	} else {
		this.setOpacity = function(e, o) { e.style.opacity = Math.min(o / 100, 0.9999); };
	}
	
}

DHTML.Base = function() {
	
	this.Base = { o: 100 };
}


DHTML.Base.prototype = {
	divX: function(x) { return DHTML.divX(this, x); },
	divY: function(y) { return DHTML.divY(this, y);  },
	
	initSelf: function() {
		var oThis = this;
		this.setLeft = function(x) { DHTML.setLeft(oThis, x); };
		this.setRight = function(x) { DHTML.setRight(oThis, x); };
		this.setTop = function(y) { DHTML.setTop(oThis, y); };
		this.setBottom = function(y) { DHTML.setBottom(oThis, y); };
		
		if (UTIL.def(this.style.filter)) {
			this.setOpacity = function(o) { this.Base.o = o; this.style.filter = 'alpha(opacity='+o+')'; };
		} else if (UTIL.def(this.style.MozOpacity)) {
			this.setOpacity = function(o) { this.Base.o = o; this.style.MozOpacity = Math.min(o / 100, 0.9999); };
		} else {
			this.setOpacity = function(o) { this.Base.o = o; this.style.opacity = Math.min(o / 100, 0.9999); };
		}
	},
	
	hScroll: function(l) { result = this.scrollLeft; if (U.def(l)) this.scrollLeft = l; return result; },
	setWidth: function(w) { DHTML.setWidth(this, w); },
	setHeight: function(h) { DHTML.setHeight(this, h); },
	moveTo: function(x, y) { this.setLeft(x); this.setTop(y); },
	sizeTo: function(w, h) { this.setWidth(w); this.setHeight(h); },
	setOpacity: function(o) { this.Base.o = o; DHTML.setOpacity(this, o); },

	getWidth: function() { return DHTML.getWidth(this); },
	getHeight: function() { return DHTML.getHeight(this); },
	getOpacity: function() { return this.Base.o; },
	
	fontSize: function(newSize) { var result = parseInt(this.style.fontSize, 10); if (typeof(newSize) != 'undefined') this.style.fontSize = newSize+'px'; return result; },
	
	center: function(h, v, e) { DHTML.center(this, h, v, e); },
	
	pageX: function() { return DHTML.pageX(this); },
	pageY: function() { return DHTML.pageY(this); },

	show: function() { DHTML.show(this); },
	hide: function() { DHTML.hide(this); },
	display: function(d) { return DHTML.display(this, d); },
	zIndex: function(z) { return DHTML.zIndex(this, z); },	

	pos: function(s) { var key; for (key in s) this[key](s[key]); }
}


DHTML.Anim = function() {
	this.Anim = { };
	this.inherit(OO.Timer);
}


DHTML.Anim.prototype = {
	
	initSelf: function() {
		this.animDeferCount = 0;
		this.X = this.divX;
		this.Y = this.divY;
		this.F = this.fontSize;
		this.SL = this.hScroll;
		this.oX = function(offset) { if (U.def(offset)) { this.divX(this.divX()+offset); if (this._offsetX) this._offsetX(offset); } return 0;};
		this.oY = function(offset) { if (U.def(offset)) { this.divY(this.divY()+offset); if (this._offsetY) this._offsetY(offset); } return 0;};
		this.W = function(w) { r = this.getWidth(); if (U.def(w)) this.setWidth(w); return r; };
		this.H = function(h) { r = this.getHeight(); if (U.def(h)) this.setHeight(h); return r; };
		this.O = function(o) { r = this.getOpacity(); if (U.def(o)) this.setOpacity(o); return r; };
	},
	
	stopAnimation: function() {
		this.clearInterval('animate');
	},
	
	animate: function(s, t, d) {
		if (U.def(d)) { this.setTimeout('delay_'+this.animDeferCount, d, this.animate, s, t); this.animDeferCount++; return; }
		this.Anim = { current: 0, direc: 1, paths: { } };
		var key;
		for (key in s) { 
			this.Anim.paths[key] = DHTML._path(this[key](), s[key], t);  
			if ((key == 'oX') || (key == 'oY')) {
				var total = 0;
				for (index = 0; index < this.Anim.paths[key].length; index++) {
					this.Anim.paths[key][index] -= total;
					total += this.Anim.paths[key][index];
				}
			}
		}
		
		this.setInterval('animate', 25, this._animate);
	},

	_animate: function() {
		var val;
		for (key in this.Anim.paths) {	
			if (!U.def(val = this.Anim.paths[key][this.Anim.current])) { this.clearInterval('animate'); return; }
			this[key](val);
		}
		this.Anim.current += this.Anim.direc;
	}
}

DHTML.Event = function() {
	this.Events = {  }
}

DHTML.Event.prototype = {
	EventHandler: function(e) {
		e = EVENT._event(e);
		var list; 
		if (!(list = this.Events[e.type])) return;
		
		for (var h,i=0;(h = list[i]);i++) if (h.call(this, e)==false) return false;
	},
	
	addListener: function(type, fn) {
		this['on'+type] = this.EventHandler;
		(this.Events[type] = this.Events[type] || [ ]).unshift(fn);
	}
}

DHTML.Drag = function() {
	this.inherit(DHTML.Event);
	this.inherit(DHTML.Anim);
}
DHTML.Drag.prototype = {

	initSelf: function() {
		this.Drag = { active: false, clone: null, constrain: null, enabled: true };
		this.addListener('mousedown', this._dragMousedown);
	},
	
	setClone: function(clone) { this.Drag.clone = DOM.get(clone);	},
	setScroll: function(scrollEle) { this.Drag.scrollEle = DOM.get(scrollEle);	},
	setDragHandle: function(handle) { this.Drag.handle = handle; },
	enableDrag: function() { this.Drag.enabled = true; },
	disableDrag: function() { this.Drag.enabled = false; },	
	setConstrain: function(constrainEle, t, r, b, l) {
		this.Drag.constrainDelta = { t: (t) ? t : 0, r: (r) ? r : 0, b: (b) ? b : 0, l: (l) ? l : 0 };
		this.Drag.constrainEle = DHTML.get(constrainEle);
	},
	
	_dragMousedown: function(e) {
		var oThis = this;
		if (!this.Drag.enabled) return;
		if (this.Drag.active) return;
		if (!this.testDragTarget(e.target)) return;
		this.Drag.init = {	event: e,
								mousemove: EVENT.attachEvents(document, 'mousemove', function(evt) { oThis._dragInit(evt); }),
								mouseup: EVENT.attachEvents(document, 'mouseup', function(evt) { oThis._dragAbort(evt); }) };
		EVENT.stopAll(e);
		return false;
	},
	
	_dragInit: function() {
		var e = this.Drag.init.event;
		var oThis = this;
		
		EVENT.removeEvents(this.Drag.init.mousemove, this.Drag.init.mouseup);		
		if (this.Drag.clone) { 
			this.Drag.clone._cloneDrag(this, e);
			
			EVENT.stopAll(e);
			return false;
		}
		
		this.Drag.dragHandle = e.target; 
		this.Drag.start = { x: this.X(), y: this.Y(), mX: e.pageX, mY: e.pageY }; 
		this.Drag.delta = { x: 0, y: 0 };
		this.Drag.current = U.copy(this.Drag.start);
		this.Drag.actual = U.copy(this.Drag.start);

		this.Drag.events = {	mousemove: EVENT.attachEvents(document, 'mousemove', function(evt) { oThis._dragMousemove(evt); }),
								mouseup: EVENT.attachEvents(document, 'mouseup', function(evt) { oThis._dragMouseup(evt); }) };
		this.setDragConstraints();
		this.onDragStart();
		
		this.setInterval('dragging', 100, this.onDrag);
		if (this.Drag.scrollEle) this.setInterval('scrolling', 100, this._scrollCheck);
		
		this.Drag.active = true;
		
		EVENT.stopAll(e);
		return false;
	},
	
	_dragAbort: function() {
		EVENT.removeEvents(this.Drag.init.mousemove, this.Drag.init.mouseup);
		this.Drag.init = { };
	},
	
	_dragMousemove: function(e) { 
		var dX,dY; 
		
		dX = e.pageX - this.Drag.current.mX;
		dY = e.pageY - this.Drag.current.mY;
		
		this.Drag.actual.x  = (this.Drag.current.x += dX); 
		this.Drag.actual.y  = (this.Drag.current.y += dY);
		this.Drag.delta.x = (this.Drag.actual.x - this.Drag.start.x);
		this.Drag.delta.y = (this.Drag.actual.y - this.Drag.start.y);
		this.Drag.current.mX = e.pageX;
		this.Drag.current.mY = e.pageY;
				
		this._dragConstrain();
		
		this.onDragMove();

		EVENT.stopAll(e);
		return false;
	},
	
	_dragMouseup: function(e) { 
		EVENT.removeEvents(this.Drag.events.mousemove);
		EVENT.removeEvents(this.Drag.events.mouseup);
		this.clearInterval('dragging');
		this.clearInterval('scrolling');
		
		this.Drag.active = false;
		this.onDragEnd();

		EVENT.stopAll(e);
		
		return false;
	},

	_dragConstrain: function() {
		if (this.Drag.constrain) {
			this.Drag.actual.x = Math.max(this.Drag.constrain.minX, Math.min(this.Drag.constrain.maxX, this.Drag.actual.x));
			this.Drag.actual.y = Math.max(this.Drag.constrain.minY, Math.min(this.Drag.constrain.maxY, this.Drag.actual.y));
		}
	},
	
	_offsetX: function(offset) { if (this.Drag.current) this.Drag.current.x += offset; },
	_offsetY: function(offset) { if (this.Drag.current) this.Drag.current.y += offset; },
	
	_cloneDrag: function(ele, e) {
		this.Drag.dragEle = ele;
		this.Drag.init = ele.Drag.init;
		this.innerHTML = '';
		this.appendChild(ele.cloneNode(true));
		this.firstChild.id = '';
		this.moveTo(DHTML.pageX(ele) - (DHTML.pageX(this) - DHTML.divX(this)), DHTML.pageY(ele) - (DHTML.pageY(this) - DHTML.divY(this)));
		this.sizeTo(DHTML.getWidth(ele), DHTML.getHeight(ele));
		this.show(this);
		this._dragInit(e);
	},
	
	_scrollCheck: function() {
		var s = this.Drag.scrollEle;
		var px = s.pageX();
		var py = s.pageY();
		var t =  this.Drag.current.mY - py;
		var l =  this.Drag.current.mX - px;
		var b =  py + s.getHeight() - this.Drag.current.mY;
		var r =  px + s.getWidth() - this.Drag.current.mX;

		if (t < 20) s.scrollTop -= (20 - (Math.max(t, 0)))
		else if (b < 20) s.scrollTop += (20 - (Math.max(b, 0)));
		if (l < 20) s.scrollLeft -= (20 - (Math.max(l, 0)))
		else if (r < 20) s.scrollLeft += (20 - (Math.max(r, 0)));
	},
	
	onDragMove: function() { this.moveTo(this.Drag.actual.x, this.Drag.actual.y); },
	onDrag: function() { },
	onDragStart: function() { },
	onDragEnd: function() { },

	testDragTarget: function(t) {
		if (!t) return false;
		if (t.noDrag) return false;
		if (this.Drag.handle) {
			if (t == this) return false;
			if (t == this.Drag.handle) return true;
			return this.testDragTarget(t.parentNode);
		}
		if (t == this) return true;
		
		return this.testDragTarget(t.parentNode);
	},
	
	setDragConstraints: function() {
		if (this.Drag.constrainEle) {
			var d = this.Drag.constrainDelta;
			var x = this.Drag.constrainEle.pageX() - this.offsetParent.pageX();
			var y = this.Drag.constrainEle.pageY() - this.offsetParent.pageY();
			this.setConstraintRect(y + d.t, x + this.Drag.constrainEle.getWidth() - d.r, y + this.Drag.constrainEle.getHeight() - d.b, x + d.l);
		} else {
			this.setConstraintRect(0, DHTML.clientWidth(), DHTML.clientHeight(), 0);
		}
	},
	
	setConstraintRect: function(minY, maxX, maxY, minX) {
		this.Drag.constrain = { minX: minX, minY: minY, maxX: maxX - this.W(), maxY: maxY - this.H() };
	}
	
	}
	
DHTML.PageResizer = function() {
	this.inherit(OO.Timer, OO.Broadcaster);
	this.Page = { width: 0, height: 0 };
	}
DHTML.PageResizer.prototype = {
	initSelf: function(controller) {
		this.setInterval('pageResizeCheck', 200, this._resizePage);
		this.addListener(controller); 
	},
	
	_resizePage: function() {
		var width = DHTML.clientWidth();
		var height = DHTML.clientHeight();

		if ((width == this.Page.width) && (height == this.Page.height)) return;
	
		this.Page.width = width;
		this.Page.height = height;
		this.sendMessage('pageResized', { width: width, height: height } );
	}
}

DHTML.EditField = function() {
}
DHTML.EditField.prototype = {
	initSelf: function() {
		this.clickEvent = EVENT.attachEvents(this, 'dblclick', this.editMode);
		this.inEditMode = false;
		this.disabledMode = false;
		this.useClassName = 'editField';
	},
	
	editMode: function(e) { 
		if (this.inEditMode || this.disabledMode) return;

		var oThis = this;
		var blurFn = function() { oThis.normalMode(); }

		this.fContent = this.innerHTML;
		this.input = DOM.structure( { t: 'input', e: { className: this.useClassName, value: this.fContent, onblur: blurFn, noDrag: 1 } } );
		this.parentNode.replaceChild(this.input, this);
		this.input.select();
		this.inEditMode = true;
		
		EVENT.stopAll(e); return false;
	},
	
	normalMode: function(e) {
		if (!this.inEditMode) return;
		
		this.innerHTML = this.fContent = this.input.value;
		
		this.input.parentNode.replaceChild(this, this.input);
		this.inEditMode = false;
	},
	
	disable: function(d) { this.disabledMode = true; },
	enable: function(d) { this.disabledMode = false; },
	
	disposeSelf: function() {
		EVENT.removeEvents(this.clickEvent);
	}
}
