/**
 * @author: Ivan Andonov
 * @email:  ivata[at]design[dot]bg
 *
 * @require: dbg.ShortcutCall
 * @use:     dbg.Style, dbg.Arrays, dbg.Objects
 **/

dbg.Utils = {
	
	parent : dbg,
	
	toString : function() {
		return this.parent+'.Utils';
	},
	
	// FUNCTION
	
	callJS : function() {
		var arr = dbg.Arrays.copyArray(arguments);
		return eval(arr[0]).apply(null, arr.slice(1));
	},

	// BROWSER SPECIFIC
	
	// browser check
	isOpera : function() {
		return navigator.userAgent.indexOf('Opera') != -1;
	},
	
	isIE : function() {
		return navigator.userAgent.indexOf('MSIE') != -1;
	},
	
	isIE6 : function() {
		return !!navigator.appVersion.match(/MSIE 6/i);
	},
	isIE7 : function() {
		return !!navigator.userAgent.match(/MSIE 7/i);
	},
	
	isMoz : function() {
		return !!navigator.userAgent.match(/gecko/i);
	},
	
	// find elements
	element : function(layer) {
		if (!layer || typeof(layer) != 'string' || !layer.length) {
			return layer;
		}
		return document.getElementById(layer);
	},
	
	getElementsByClassName : function(layer, classes, strTagName, match, conversely) {
		layer = $e(layer) || $body();
		var result = [];
		if (layer) {
			if (strTagName == null) {
				strTagName = '*';
			}
			var arrElements = [];
			if (strTagName == '*' && layer.all != null) {
				arrElements = layer.all;
			} else if (layer.getElementsByTagName != null) {
				arrElements = layer.getElementsByTagName(strTagName);
			} else if (layer.all != null) {
				arrElements = layer.all;
			}
			var elmnt;
			for (var i = 0; i < arrElements.length; i++) {
				elmnt = arrElements[i];
				if (classes == null) {
					if (!elmnt.className.length) {
						if (!conversely) {
							result.push(elmnt);
						}
					} else if (conversely) {
						result.push(elmnt);
					}
				} else if ((elmnt.className && elmnt.className.length) || conversely) {
					var elmntClasses = elmnt.className.split(' ');
					if (typeof(classes) == 'string') {
						if (classes == '*') {
							if (elmnt.className.length) {
								if (!conversely) {
									result.push(elmnt);
								}
							} else if (conversely) {
								result.push(elmnt);
							}
						} else {
							if (match) {
								var matched = 0;
								var tmpClasses = classes.split(' ');
								dbg.Objects.each(
									elmntClasses,
									function(props, value, obj) {
										if (dbg.Arrays.inArray(tmpClasses, value)) {
											matched++;
										}
									}
								);
								/*for (var cls in elmntClasses) {
									if (dbg.Arrays.inArray(tmpClasses, elmntClasses[cls])) {
										matched++;
									}
								}*/
								if (matched == tmpClasses.length) {
									if (!conversely) {
										result.push(elmnt);
									}
								} else if (conversely) {
									result.push(elmnt);
								}
							} else if (elmnt.className == classes) {
								if (!conversely) {
									result.push(elmnt);
								}
							} else if (conversely) {
								result.push(elmnt);
							}
						}
					} else if (typeof(classes) == 'object' && classes.length) {
						var doAdd = false;
						for (var j = 0; j < classes.length; j++) {
							if (!dbg.Arrays.inArray(result, elmnt)) {
								if (match) {	
									var matched = 0;
									var tmpClasses = classes[j].split(' ');
									dbg.Objects.each(
										elmntClasses,
										function(prop, value, obj) {
											if (dbg.Arrays.inArray(tmpClasses, value)) {
												matched++;
											}
										}
									);
									/*for (var cls in elmntClasses) {
										if (dbg.Arrays.inArray(tmpClasses, elmntClasses[cls])) {
											matched++;
										}
									}*/
									if (matched == tmpClasses.length) {
										if (!conversely) {
											doAdd = true;
										} else {
											doAdd = false;
											break;
										}
									} else if (conversely) {
										doAdd = true;
									}
								} else if (classes[j] == elmnt.className) {
									if (!conversely) {
										doAdd = true;
									} else {
										doAdd = false;
										break;
									}
								} else if (conversely) {
									doAdd = true;
								}
							}
						}
						if (doAdd) result.push(elmnt);
					}
				}
			}
		}
		return result;
	},
	
	getBody : function() {
		return document.body || document.getElementsByTagName('body')[0];
	},
	
	getHead : function() {
		return document.getElementsByTagName('head')[0];
	},
	
	getFlashMovie : function(id) {
		if (window.document[id]) {
			return window.document[id];
		}
		if (!isIE()) {
			if (document.embeds && document.embeds[id]) {
				return document.embeds[id];
			}
		}
		return document.getElementById(id);
	},
	
	// element position
	getElementX : function(el) {
		el = $e(el);
		var x = 0;
		if (el) {
			if (el.offsetParent) {
				x = el.offsetLeft;
				el = el.offsetParent
				while (el) {
					x += el.offsetLeft;
					el = el.offsetParent
				}
			} else if (el.x) {
				x = el.x;
			}
		}
		return x;
	},
	
	getElementY : function(el) {
		el = $e(el);
		var y = 0;
		if (el) {
			if(el.offsetParent) {
				y = el.offsetTop;
				el = el.offsetParent
				while(el) {
					y += el.offsetTop;
					el = el.offsetParent
				}
			} else if (el.y) {
				y = el.y;
			}
		}
		return y;
	},
	
	getElementWidth : function(obj) {
		obj = $e(obj);
		return obj ? obj.offsetWidth : 0;
	},
	
	getElementHeight : function(obj) {
		obj = $e(obj);
		return obj ? obj.offsetHeight : 0;
	},
	
	// page offset
	getPageXScroll : function() {
		//return (window.pageXOffset ? window.pageXOffset : (document.documentElement && document.documentElement.scrollLeft != null) ? document.documentElement.scrollLeft : document.body.scrollLeft)||0;
		return Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
	},
	
	getPageYScroll : function() {
		//return (window.pageYOffset ? window.pageYOffset : (document.documentElement && document.documentElement.scrollTop != null) ? document.documentElement.scrollTop : document.body.scrollTop)||0;
		return Math.max(document.documentElement.scrollTop, document.body.scrollTop);
	},
	
	// document and screen dimentions
	getDocumentHeight : function() {
		var scrollHeight = (document.compatMode != 'CSS1Compat') ? document.body.scrollHeight : document.documentElement.scrollHeight;
		return Math.max(scrollHeight, this.getViewportHeight());
	},
	
	getDocumentWidth : function() {
		var scrollWidth = (document.compatMode != 'CSS1Compat') ? document.body.scrollWidth : document.documentElement.scrollWidth;
		return Math.max(scrollWidth, this.getViewportWidth());
	},
	
	getViewportHeight : function() {
		var mode = document.compatMode;
		if ((mode || this.isIE()) && !this.isOpera()) { // IE, Gecko
			return (mode == 'CSS1Compat') ? document.documentElement.clientHeight : document.body.clientHeight; // ? Standards : Quirks
		}
		return self.innerHeight; // Safari, Opera
	},
	
	getViewportWidth : function() {
		var mode = document.compatMode;
		if (mode || this.isIE()) { // IE, Gecko, Opera
			return (mode == 'CSS1Compat') ? document.documentElement.clientWidth : document.body.clientWidth; // ? Standards : Quirks
		}
		return self.innerWidth; // Safari
	},

	// Focus
	
	focus : function(el) {
		try {
			$e(el).focus();
		} catch(e){};
	},
	
	blur : function(el) {
		try {
			$e(el).focus();
		} catch(e){};
	},
	
	onFocus : function(el, def, select, toPass) {
		el = $e(el);
		if (el && el.value == def) {
			el.value = '';
			if (toPass) {
				el.type = 'password';
			}
			if (select) {
				el.select();
			}
		}
	},
	
	onBlur : function(el, def, toText) {
		el = $e(el);
		if (el && !el.value.split(' ').join('').length) {
			el.value = def;
			if (toText) {
				el.type = 'text';
			}
		}
	},
	
	// class manipulation
	addClass : function(el, cls) {
		el = $e(el);
		if (el) {
			var found = false;
			if (!el.className) {
				el.className = '';
			}
			if (el.className.length) {
				var classes = el.className.split(' ');
				for (var i = 0, len = classes.length; i < len; i++) {
					if (classes[i] == cls) {
						found = true;
						break;
					}
				}
			}
			if (!found) {
				el.className = (el.className.length ? el.className+' ' : '')+cls;
			}
		}
	},
	
	removeClass : function(el, cls) {
		el = $e(el);
		if (el) {
			var classes = el.className.split(' ');
			var className = '';
			for (var i = 0, len = classes.length; i < len; i++) {
				if (classes[i].length && classes[i] != cls) {
					className += (className.length ? ' ' : '')+classes[i];
				}
			}
			el.className = className;
		}
	},
	
	haveClass : function(el, cls) {
		el = $e(el);
		if (el) {
			if (!el.className) {
				return false;
			}
			var classes = el.className.split(' ');
			return dbg.Objects.each(
				classes,
				function(prop, value, obj) {
					if (cls == value) {
						return true;
					}
				}
			);
			/*for (var i in classes) {
				if (cls == classes[i]) {
					return true;
				}
			}*/
			return false;
		}
		return null;
	},
	
	// visibility of the elements
	showElements : function() {
		for (var i = 0; i < arguments.length; i++) {
			$style(arguments[i], 'display', 'block');
		}
	},
	
	hideElements : function() {
		for (var i = 0; i < arguments.length; i++) {
			$style(arguments[i], 'display', 'none');
		}
	},
	
	switchElements : function() {
		for (var i = 0; i < arguments.length; i++) {
			$style(arguments[i], 'display', this.isVisible(arguments[i]) ? 'none' : 'block');
		}
	},
	
	isVisible : function(id) {
		return $style(id, 'display') != 'none';
	},

	// Content
	
	setHtml : function(id, str) {
		$e(id).innerHTML = str;
	},
	
	getHtml : function(id, str) {
		return $e(id).innerHTML;
	},

	// HTML ELEMENTS
	
	selects : null,
	
	isSelectsVisible : true,
	
	// show hide all select elements
	showSelects : function() {
		//Debug.log('showSelects');
		if (!this.isSelectsVisible) {
			dbg.Objects.each(this.selects, function(prop, value, obj) {
				$style(value, 'visibility', 'visible');
			});
			/*for (var i in this.selects) {
				$style(this.selects[i], );
			}*/
			this.isSelectsVisible = true;
		}
	},
	
	hideSelects : function() {
		//Debug.log('hideSelects');
		if (this.isSelectsVisible) {
			if (this.selects == null) {
				this.selects = document.getElementsByTagName('select');
			}
			dbg.Objects.each(this.selects, function(prop, value, obj) {
				$style(value, 'visibility', 'hidden');
			});
			/*for (var i in this.selects) {
				$style(this.selects[i], 'visibility', 'hidden');
			}*/
			this.isSelectsVisible = false;
		}
	},

	// LOCATION
	
	genObjectFromQuery : function(str) {
		if (str) {
			var obj= {};
			var prop;
			var props = str.split('&');
			for (var i = 0; i < props.length; i++) {
				prop = props[i].split('=');
				if (i == 0) {
					if (prop[0].indexOf('?') != -1) {
						prop[0] = prop[0].substr(prop[0].indexOf('?')+1);
					}
				}
				obj[prop[0]] = prop[1];
			}
			return obj;
		}
		return null;
	},
	
	getQueryParamValue : function(param, str) {
		var q = str || document.location.search || document.location.href.hash;
		if (q) {
			var startIndex = q.indexOf(param+'=');
			var endIndex = (q.indexOf('&', startIndex) > -1) ? q.indexOf('&', startIndex) : q.length;
			if (q.length > 1 && startIndex > -1) {
				return q.substring(q.indexOf('=', startIndex)+1, endIndex);
			}
		}
		return '';
	},
	
	getQueryObj : function(str) {
		var q = str || document.location.search || document.location.href.hash;
		if (!q.indexOf('?')) q = q.substr(1);
		var obj = {};
		if (q) {
			var arr = q.split('&');
			var arr1;
			for (var i = 0,len = arr.length; i < len; i++) {
				arr1 = arr[i].split('=');
				if (arr1[0].indexOf('?') != -1) {
					arr1[0] = arr1[0].substr(arr1[0].indexOf('?')+1);
				}
				obj[arr1[0]] = arr1[1];
			}
		}
		return obj;
	},
	
	isLocal : function() {
		return document.location.href.indexOf('file:') == 0;
	},
	
	/*--------------------
		Customizing
	--------------------*/
	// even/odd styling
	stripe : function(layer, tags, evenClass, oddClass, everyN, oddIsFirst, leaveHeights) {
		if (!everyN) everyN = 1;
		var even = oddIsFirst;
		var mainObj;
		if (!(mainObj = $e(layer))) {
			return;
		}
		if (!evenClass) {
			evenClass = 'even';
		}
		if (!oddClass) {
			oddClass = 'odd';
		}
		var elements = this.getElementsIn(mainObj, tags, 0);
		var el;
		var tmp = [];
		var maxH = 0;
		for (var i = 0; i < elements.length; i++) {
			el = elements[i];
			if (!(i%everyN)) {
				even = !even;
				el.style.clear = 'left';
			} else {
				el.style.clear = '';
			}
			el.className = even ? evenClass : oddClass;
			if (!leaveHeights) {
				$style(el, 'height', this.isIE6() ? 0 : 'auto');
				//$style(el, 'height', 'auto');
				if (el.style.clear == 'left') {
					for (var n = 0; n < tmp.length; n++) {
						$style(tmp[n], 'height', maxH+'px');
					}
					tmp = [];
					maxH = 0;
				}
				maxH = Math.max(this.getElementHeight(el), maxH);
				//Debug.log(el.innerHTML+' '+this.getElementHeight(el)+' '+maxH);
				tmp.push(el);
			}
		}
	},
	
	getElementsIn : function(obj, tags, depth, elements) {
		if (!elements) {
			elements = [];
		}
		if (!depth) {
			depth = 0;
		}
		var els = obj.getElementsByTagName(tags[depth]);
		if (tags[depth+1]) {
			for (var i = 0; i < els.length; i++) {
				elements = arguments.callee(els[i], tags, depth+1, elements);
			}
		} else {
			for (var i = 0; i < els.length; i++) {
				elements.push(els[i]);
			}
		}
		return elements;
	},
	
	// OTHERS
	// remove a flickering
	fixBgImageCache : function() {
		try {
			document.execCommand('BackgroundImageCache', false, true);
		} catch(e) {}
	}
	
}

dbg.Utils.fixBgImageCache();

$shortcut(['e', 'element'], dbg.Utils, 'element');

$shortcut('body', dbg.Utils, 'getBody');

$shortcut('stripe', dbg.Utils, 'stripe');

$shortcut('head', dbg.Utils, 'getHead');

$shortcut('html', dbg.Utils, function(){
	if (arguments.length == 1) {
		dbg.Utils.getHtml.apply(dbg.Utils, arguments);
	} else {
		dbg.Utils.setHtml.apply(dbg.Utils, arguments);
	}
});