/*!
*	Copyright (c) 2007 Bethke et al. GmbH, Berlin, Germany copyright@b-et-a.de
* All rights reserved.
* Authors:
	Ingo Struck - seen at ingostruck dot de
	Mathias Schaefer - mathias.schaefer at 9elements dot com
*/

// we explicitly want to 'poison the namespace' with these two specials
/*
// not used at the moment (it's shorter to write '"property" in obj' anyway)
function isDef (obj, fld) {
	if (!obj) obj = window;
	return 'undefined' != typeof obj[fld];
}
*/
function $(id) { return document.getElementById(id); }

// unpoisoned stuff follows ;-)

var cookie = {

	set : function (key,val,duration) {
		if (duration) {
			var date = new Date();
			date.setTime(date.getTime()+(duration*24*60*60*1000));
			var exp = '; expires='+date.toGMTString();
		} else var exp = '';
		var dom = util.topdom();
		dom = dom.replace(/^secure./, '');
		dom = dom.replace(/^edit./, '');
		document.cookie = key+'='+val+exp+"; domain=."+dom+'; path=/';
	},

	tab : function () {
		var cook = document.cookie;
		if (!cook || 0 == cook.length) return false;
		var spl = cook.split(';');
		var cval = new Object();
		for ( var idx = 0; idx < spl.length; ++idx ) {
			var keyval = util.trim(spl[idx]).split('=');
			if ( 2 != keyval.length ) continue;
			cval[util.trim(keyval[0])] = util.trim(keyval[1]);
		}
		return cval;
	},

	screen : function () {
		var ctab = cookie.tab();
		var spl = util.skin_split( ctab );
		var skin = ctab.skin || false;
		if ( !skin || (screen.availHeight != spl[0]) || (screen.availWidth != spl[1])) {
			cookie.set('skin',skin,-1);
			spl[0] = screen.availWidth;
			spl[1] = screen.availHeight;
			cookie.set('skin',spl.join(':'),3650); // ten years
		}
	}
	
}; // var cookie

var util = {
	body: false,
	page: false,
	skin: '1',

	stamp: function () {
		var d = new Date();
		var year = '' + d.getUTCFullYear();
		var mon = '' + (d.getUTCMonth() + 1);
		if ( 2 > mon.length ) mon = '0' + mon;
		var day = '' + d.getUTCDate();
		if ( 2 > day.length ) day = '0' + day;
		var hour = '' + d.getUTCHours();
		if ( 2 > hour.length ) hour = '0' + hour;
		var min = '' + d.getUTCMinutes();
		if ( 2 > min.length )	min = '0' + min;
		var sec = '' + d.getUTCSeconds();
		if ( 2 > sec.length ) sec = '0' + sec;
		return year+mon+day+hour+min+sec;
	},

	trim: function ( str ) { return str ? str.replace(/^\s*/,'').replace(/\s*$/,'') : str; },

	copy: function (src,tgt) {
		if (!src) return src;
		if (!tgt) tgt = {};
		for ( var prop in src ) {
			var val = src[prop];
			if ( src == val || undefined == val ) continue;
			tgt[prop] = val;
		}
		return tgt;
	},

	/*
		try to make an event halfway DOM conformant
	*/
	uni_event: function (evt, prop) {
		
		var oEvt = evt || window.event;
		if (!oEvt) return false;
		
		evt = util.copy(oEvt);

		// general
		if (!evt.target && evt.srcElement) evt.target = evt.srcElement;
		if (!evt.relatedTarget && evt.fromElement)
			evt.relatedTarget = evt.fromElement == evt.target ? evt.toElement : evt.fromElement;
		/* TODO: check if we need the safari/textnode hack
			if (safari && 3 == evt.target.nodeType) evt.target = oEvt.target.parentNode;
		*/
		// key
		if (!evt.which && (evt.charCode || evt.keyCode)) evt.which = evt.charCode || evt.keyCode;
		if (!evt.metaKey && evt.ctrlKey) evt.metaKey = evt.ctrlKey;
		// mouse
		if ( null == evt.pageX && null != evt.clientX ) {
			var doc_e = document.documentElement, doc_b = document.body;
			evt.pageX = evt.clientX + (doc_e && doc_e.scrollLeft || doc_b.scrollLeft || 0);
			evt.pageY = evt.clientY + (doc_e && doc_e.scrollTop || doc_b.scrollTop || 0);
		}
		if (!evt.which && evt.button )
			evt.which = (1&evt.button ? 1 : (2&evt.button ? 3 : (4&evt.button ? 2 : 0 )));

		// propagate/bubble control
		if (prop) {
			evt.preventDefault = function () {
				if (oEvt.preventDefault) oEvt.preventDefault();
				oEvt.returnValue = false;
			};
			evt.stopPropagation = function () {
				if (oEvt.stopPropagation) oEvt.stopPropagation();
				oEvt.cancelBubble = true;
			};
		} else {
			// turn it off
			if (oEvt.preventDefault) oEvt.preventDefault();
			if (oEvt.stopPropagation) oEvt.stopPropagation();
			oEvt.returnValue = false;
			oEvt.cancelBubble = true;
		}

		return evt;
	},

	add_event: function (obj, typ, fun) {
		if (obj.addEventListener) {
			obj.addEventListener( typ, fun, false); 
			return true; 
		} else if (obj.attachEvent) {
			obj['e'+typ+fun] = fun;
			obj[typ+fun] = function() { obj['e'+typ+fun]( window.event ); }
			return obj.attachEvent('on'+typ, obj[typ+fun]);
		}
		return false;
	},


	mouseenter : function (evt, currentTarget) {
		return (evt && currentTarget && evt.relatedTarget && currentTarget != evt.relatedTarget && !currentTarget.contains(evt.relatedTarget));
	},

/*
	// not used any more?
	// very special crap to allow for old-style nested cascading
	add_onLoad : function (fun) {
		var ool = window.onload;
		var nol = fun;
		if ('function' == typeof window.onload) nol = function() { if (ool) ool(); fun();	};
		window.onload = nol;
	},
*/

	pre_style: function (that, what) {
		// first catch IE crap
		if ( document.createStyleSheet ) {
			document.createStyleSheet("javascript:'" + that + " {" + what + "}'");
			return;
		}

		if (!document.getElementsByTagName || !document.createElement)
			return;

		var head = document.getElementsByTagName('head')[0];
		var style = document.createElement('style');
		style.type = 'text/css';
		style.media = 'screen';
		var styleRule = document.createTextNode(that + ' { ' + what + ' }');
		style.appendChild(styleRule);
		head.appendChild(style);
	},

	viewPort: function () {
		if (self.innerHeight)
			return [self.innerWidth, self.innerHeight];
		if (document.documentElement && document.documentElement.clientHeight)
			return [document.documentElement.clientWidth, document.documentElement.clientHeight];
		if (document.body)
			return [document.body.clientWidth, document.body.clientHeight];
		return [0,0];
	},

	off_elem: function (elem) {
		var x=0,y=0;
		while (elem) {
			x += elem.offsetLeft;
			y += elem.offsetTop;
			elem = elem.offsetParent;
		}
		return [x,y];
	},

	off_scroll: function () {
		if (null!=window.pageYOffset) return [window.pageXOffset,window.pageYOffset];
		if (null!=document.documentElement && null!=document.documentElement.scrollTop) return [
			document.documentElement.scrollLeft, document.documentElement.scrollTop
		];
		if (null!=document.body) return [document.body.scrollLeft,document.body.scrollTop];
		// you lose
		return [false,false];
	},

	off_mouse: function (e) {
		var x=0,y=0;
		if (!e) e = window.event;
		if (null!=e.pageX && null!=e.pageY) return [e.pageX, e.pageY];
		if (null!=e.clientX && null!=e.clientY) return [
			e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft,
			e.clientY + document.body.scrollTop + document.documentElement.scrollTop
		];
		// you lose
		return [false,false];
	},

	addSubDiv: function (div,style) {
		var e=document.createElement("div");
		e.className=style;
		div.appendChild(e);
		return e;
	},

	// return: [my_dom, the_dom, port:]
	url2dom: function ( url ) {
		if (!url) return false;
		var ret = [false,false,false];
		var dom = url;
		var port = '';
		var s = dom.indexOf('://');
		if ( 0 <= s ) dom = dom.substring(s+3);
		var e = dom.indexOf('/');
		if ( 0 <= e ) dom = dom.substring(0,e);
		e = dom.indexOf(':');
		if ( 0 <= e ) {
			port = dom.substring(e); // including ':'
			dom = dom.substring(0,e);
		}
		ret[0] = dom;
		e = dom.lastIndexOf('.'); //skip tld
		e = dom.lastIndexOf('.',e-1);
		if ( 0 <= e ) dom = dom.substring(e+1);
		ret[1] = dom;
		ret[2] = port;
		return ret;
	},

	topdom: function () {
		return util.url2dom(document.URL)[1];
	},

	mydom : function () {
		return util.url2dom(document.URL)[0];
	},

/*
	// not used any more?
	get_operator: function () {
		var div = document.getElementById('operator');
		if (div) return div;
		div = addDynDiv('operator',710,120,300,400,5,false,true,20);
		div.id = 'operator';
		div._header.innerHTML += 'operator';
		div.style.display='block';
		return div;
	},
*/

	get_my: function () {
		var div = document.getElementById('my');
		if (div) return div;

		var stage = document.getElementById('stage');
		var eo = off_elem(stage);
	
		div = addDynDiv('my',800+eo[0],eo[1],170,400,5,false,true,20);
		div.id = 'my';
		div._header.innerHTML += 'my';
		div.style.display='block';
		return div;
	},

	skin_split: function (ctab) {
		var spl = false;
		if (ctab && ctab.skin) {
			spl = ctab.skin.split(':');
			if (5 != spl.length) spl = false;
		}
		return spl || ['0','0','1','50','0'];
	},

	inpFoc: function (evt) {
		evt = util.uni_event(evt);
		var inp = evt.target;
		var val = inp && inp.value;
		if (!val) return false;
		var len = val.length;
		if ( 1 < len && '[' == val.charAt(0) && ']' == val.charAt(len-1) && val == inp.defaultValue) inp.value = '';
		return false;
	},

	inpBlu: function (evt) {
		evt = util.uni_event(evt);
		var inp = evt.target;
		var val = inp && inp.value;
		return false;
	},

	populateInput: function () {
		for (var i = 0; i < document.forms.length; ++i )
			for (var j = 0; j < document.forms[i].length; ++j ) {
				var inp = document.forms[i][j];
				var typ = inp.type;
				if ('text' != typ && 'textarea' != typ) continue;
				inp.onfocus = util.inpFoc;
				inp.onblur = util.inpBlu;
			}
	},

	getStyle : function (element, prop) {
		if (document.defaultView && document.defaultView.getComputedStyle)
			return document.defaultView.getComputedStyle(element, null).getPropertyValue(prop);
		if (element.currentStyle)
			return element.currentStyle[prop];
		return false;
	},

	qryTab : function (query) {
		if (!query) return {};
		if (query.charAt(0) == '?') {
			query = query.substring(1);
		}
		var pairs = query.split('&');
		var obj = {}, pair, name, value;
		for (var i = 0; i < pairs.length; i++) {
			if ('' == pairs[i]) {
				continue;
			}
			pair = pairs[i].split('=');
			name = decodeURIComponent(pair[0]);
			value = decodeURIComponent(pair[1]);
			obj[name] = value;
		}
		return obj;
	},

	onReady: function () {
		this.body = document.body;

		var ctab = cookie.tab();
		var spl = util.skin_split( ctab );
		util.skin = spl['2'];
		
		cookie.screen();
	}

}; // var util

// Prototype Extensions

if (window.Node && Node.prototype && !Node.prototype.contains) {
	Node.prototype.contains = function (arg) {
		return Boolean(this.compareDocumentPosition(arg) & 16);
	};
}

Array.prototype.clone = function () {
	return [].concat(this);
};

Array.prototype.contains = function (obj) {
	// Test JavaScript 1.6 (Gecko)
	if (typeof this.indexOf == 'function') {
		return (this.indexOf(obj) != -1);
	}
	for (var i = 0; i < this.length; i++)
		if (this[i] == obj)
			return true;
	return false;
};

/*
	Binary search
	For this function to make sense the array needs to
	- contain string or number primitives exclusively,
	- be large,
	- be sorted once in advance (outside of this function),
	- be searched more than once.
*/
/*

// not used at the moment

Array.prototype.containsPrimitive = function (obj) {
	// Test JavaScript 1.6 (Gecko)
	if (typeof this.indexOf == 'function') {
		return (this.indexOf(obj) != -1);
	}
	var left = -1;
	var right = this.length;
	var middle;
	while (right - left > 1) {
		middle = (left + right) >>> 1;
		if (this[middle] < obj) {
			left = middle;
		} else {
			right = middle;
		}
	}
	if (this[right] != obj) {
		return -(right + 1);
	}
	return right;
};
*/

Function.prototype.bind = function (object) {
	var method = this;
	var wrapper = function () {
		var args = Array.prototype.slice.call(arguments);
		return method.apply(object, args);
	};
	return wrapper;

};

Function.prototype.bindAsEventListener = function (object) {
	var method = this;
	var wrapper = function (event) {
		method.call(object, event || window.event);
	};
	return wrapper;
};

// Development/Debug stuff

var debug = {
	
	debugMode : false,
	
	on : function () {
		window.name = 'debug';
	},
	
	off : function () {
		window.name = '';
	},
	
	/*
	linearize : function (arg, noArrayBrackets) {
		if (typeof arg == 'string') {
			return "'" + arg + "'";
		} else if (typeof arg == 'function') {
			var match = arg.toString().match(/^function\s+[^\s\(]/);
			if (match) {
				return '[' + match + ']';
			} else {
				return '[function]';
			}
		} else if (typeof arg == 'object' && arg.constructor == Array) {
			var returnValue = '';
			for (var i = 0; i < arg.length; i++) {
				returnValue += arguments.callee(arg[i]);
				if (i != arg.length - 1) {
					returnValue += ', ';
				}
			}
			if (!noArrayBrackets) returnValue = '[' + returnValue + ']';
			return returnValue;
		} else if (arg.toString) {
			return arg.toString();
		} else {
			return 'linearization failed';
		}
	},
	*/

	log : function () {
	
		if (!debug.debugMode && window.name != 'debug') {
			return false;
		}
	
		if (arguments.length == 0) {
			return false;
		}
		var txt = debug.joinArray(arguments, ', ');

		if (txt == "") {
			return false;
		}
		
		if (window.console && console.log) {
			if (console.log.length == 1) {
				console.log(txt);
			} else {
				console.log.apply(console, arguments);
			}
			return true;
		}

		var logElem = debug.getLog();
		if (!logElem) {
			return false;
		}
		
		if (logElem.childNodes.length > 150) {
			debug.clearLog();
		}
		
		var div = document.createElement('div');
		div.innerHTML = txt.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g, '<br />');
		logElem.appendChild(div);
		
		logElem.scrollTop = logElem.scrollHeight;
	},

	logObj: function (obj) {
	
		if (!debug.debugMode && window.name != 'debug') {
			return false;
		}
		
		if (window.console && console.dir) {
			console.dir(obj);
			return true;
		}
		
		var output = '';
		for (var id in obj) {
			output += id + ' : ' + obj[id] + '\n';
		}
		return debug.log(output);
	},

	closeLog: function () {
		debug.off();
		var elem;
		if (elem = $('debug_log')) {
			elem.style.display = 'none';
		}
	},

	clearLog: function () {
		var elem = debug.getLog();
		if (!elem) return false;
	
		var divs = elem.getElementsByTagName('div');
		for (var i = divs.length - 1; i >= 0; i--)
			elem.removeChild(divs[i]);
	},

	getLog : function () {
		var elem = $('debug_log');
		
		if (elem) {
			return elem;
		}
		
		if (!document.body) {
			return false;
		}

		var head = document.getElementsByTagName('head')[0];

		var stylesheet;
		stylesheet = document.createElement('link');
		stylesheet.rel = 'stylesheet';
		stylesheet.type = 'text/css';
		stylesheet.href = '/msch/css/debug.css';
		head.appendChild(stylesheet);
		
		elem = document.createElement('div');
		elem.id = 'debug_log';
		document.body.appendChild(elem);

		var clearButton = document.createElement('input');
		clearButton.type = 'button';
		clearButton.value = 'clear';
		clearButton.onclick = debug.clearLog;
		elem.appendChild(clearButton);

		var closeButton = document.createElement('input');
		closeButton.type = 'button';
		closeButton.value = 'close';
		closeButton.onclick = debug.closeLog;
		elem.appendChild(closeButton);
		
		return elem;
	},
	
	joinArray : function (args, jointer) {
		jointer = jointer || " ";
		return Array.prototype.slice.apply(args).join(jointer);
	}
	
};

// Development/Debug Stuff Ends
