// General UI Utilities
function UIUtil() {

}

// Calls parents function, useful for oo inheritance in js
UIUtil.CallParentFn = function(child, parentFn){
	if (arguments.length > 2){
		parentFn.apply(child, Array.prototype.slice.call( arguments, 2 ));
	} else {
		parentFn.call(child);
	}
}

// Child inherits and sets parent property
UIUtil.Inherit = function(child, parent){
	child.prototype = new parent();
	child.prototype.parent = parent.prototype;
}

UIUtil.isIE = function(){
    var userAgent = navigator.userAgent.toLowerCase();
    return (userAgent.indexOf("msie2")>=0 && document.all);
}

UIUtil.isSafari = function(){
    var userAgent = navigator.userAgent.toLowerCase();
    return (userAgent.indexOf("safari")>=0);
}

UIUtil.isFirefox = function(){
	return navigator.userAgent.indexOf("Firefox") != -1;
}

UIUtil.isOpera = function(){
	return navigator.userAgent.indexOf("Opera") != -1;
}

UIUtil.isMozilla = function(){
	var userAgent = navigator.userAgent.toLowerCase();
    var ism = userAgent.indexOf("mozilla") > -1;
	return ism;
}

UIUtil.isWin = function(){
	return navigator.userAgent.indexOf(" Windows ") != -1;
}

UIUtil.isMac = function(){
	return navigator.userAgent.indexOf(" Mac ") != -1;
}

UIUtil.isLinux = function(){
	return navigator.userAgent.indexOf(" Linux ") != -1;
}

UIUtil.pngImg = function(width, height, src, style, id){
	if (UIUtil.isIE()){
		document.write('<span id="' + id + '" style="' + style + ';width:' + width + 'px;height:' + height + 'px;' + 
				'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\',sizingMethod=\'scale\')"></span>');
	} else {
		document.write('<img id="' + id + '" width="' + width + '" height="' + height + '" src="' + src + '" style="' + style + ';"/>');
	}
}

UIUtil.setStyle = function(elem, styles){
	for(var style in styles) {
		elem.style[style] = styles[style];
	}
}

UIUtil.setAttrs = function(elem, attrs) {
	for(var attr in attrs) {
		if (typeof attrs[attr] == "function"){
			elem[attr] = attrs[attr];
		}else if (attr != "style" && attr != "value"){
			elem.setAttribute((attr.toLowerCase() == "classname" && !UIUtil.isIE() ? "class" : attr), attrs[attr]);
		}else if (attr != "value"){
			UIUtil.setStyle(elem, attrs[attr]);
		}else if (attr == "value"){
			if (typeof attrs[attr] == "string" || typeof attrs[attr] == "object" && attrs[attr] instanceof String)
				elem.appendChild(document.createTextNode(attrs[attr]));
			else if(typeof attrs[attr] == "object" && attrs[attr].nodeType != 'undefined') {
				elem.appendChild(attrs[attr]);
			}
		}
	}
}

UIUtil.genRow = function(trAttrs, cols) {
	var tr = document.createElement("tr");
	UIUtil.setAttrs(tr, trAttrs);
		
	for(var i = 0; i < cols.length; i++) {
		var td = document.createElement("td");
		UIUtil.setAttrs(td, cols[i]);
		tr.appendChild(td);
	}
	return tr;
}

UIUtil.addParams = function(elem, params) {
	for (var key in params) {
		if(params[key] != null) {
			var paramElem = document.createElement('param');
			paramElem.setAttribute(key, params[key]);
			elem.appendChild(paramElem);
		}
	}
}

UIUtil.hlightFormOnError = function(data, formElem ) {
	if(data.error != null)
		formElem.style.border = "1px solid red";
}

UIUtil.setFormItemsDisabled = function(ids, disabled, form) {
	for (var i = 0; i < ids.length; i++) {
		var formItem = form[ids[i]];
		formItem.disabled = disabled;
	}
}

UIUtil.getElem = function(elem) {
	if (typeof elem == "string" || typeof elem == "object" && elem instanceof String)
		return document.getElementById(elem);
	else
		return elem;
}

UIUtil.hideShowElem = function(elem, hide, displayStyle){
	if(hide){
		elem.style.display = "none";
	} else {
		elem.style.display = displayStyle || "inline";
	}
}

// Adds functions to body.onbeforeunload without clobbering
// old handlers.
UIUtil.addToBodyOnBeforeUnload = function(functionRef) {
	UIUtil.addEvent(window, "beforeunload", functionRef);
}

// Methods to addEvents and removeEvents, but
// avoid memory leaks.
// based on code from http://ejohn.org/projects/flexible-javascript-events/
// TODO this needs some fixing, it does not work when used inside an object's method
UIUtil.addEvent = function(obj, type, handlerFn) {
	if(obj.attachEvent) {
		// IE
		// These two lines are used to get around IE refering to "this" keyword
		// as window.this when using the attachEvent method
		// the keys 'e' + type + handlerFn and type + handlerFn are hopefully unique
		obj['e' + type + handlerFn] = handlerFn;
		obj[type + handlerFn] = function(){obj['e' + type + handlerFn](window.event);};
		// attach the event, IE assumes on is prepended to the type
		obj.attachEvent('on' + type, obj[type + handlerFn]);
	} else {
		// Others
		obj.addEventListener(type, handlerFn, false);
	}
}

UIUtil.removeEvent = function(obj, type, handlerFn) {
	if(obj.detachEvent) {
		// IE
		// detach event, IE assumes on is prepended to type
		obj.detachEvent('on' + type, obj[type + handlerFn]);
		// set references to handler to null
		obj[type + handlerFn] = null;
		obj['e' + type + handlerFn] = null;
	} else {
		// Others
		obj.removeEventListener(type, handlerFn, false);
	}
}

// If image src is a broken link, then 
// defaultUri is used.
// Firefox and IE support onerror, just set src when error occurs
// img - refrence to img element
// imgId - id of referenced img element
// defaultUri - uri of the image to display if the load fails
// timeoutInMsec - Defaults to 1500.  Time to wait, in msec, for the image to load.
// This only applies to Safari.
// serverDownCheck - Defaults to false, addCheckForBrokenImage can also be used as a hack to 
// determine whether a site is reachable.  This is used in the syndication app to display an 
// appropriate error message to users in the event that the site is unreachable.
UIUtil.addCheckForBrokenImg = function(img, imgId, defaultUri, timeoutInMsec, serverStatusCheck) {
	if (serverStatusCheck == null)
		serverStatusCheck = false;
	if (UIUtil.isFirefox() || UIUtil.isIE()) {
		// Firefox and IE have an onerror event
		if (!serverStatusCheck){
			img.onerror = function(){img.src = defaultUri;}
		} else {
			img.onerror = function(){UIUtil.checkServerStatus(null, false);}
			img.onload = function(){UIUtil.checkServerStatus(null, true);}
		}
	} else {
		// Safari does not have an onerror event
		// Instead we use onload, if onload is called set the property
		// pzComplete to true.  The image has until the timeout to load,
		// if it fails load by then it is considered broken
		if (timeoutInMsec == null)
			timeoutInMsec = 1500;
		img.onload = function(){img.pzComplete = true;}
		if (!serverStatusCheck)
			window.setTimeout("UIUtil.checkForBrokenImgLoad('" + imgId + "', '" + defaultUri + "')", timeoutInMsec);
		else
			window.setTimeout("UIUtil.checkServerStatus('" + imgId + "', null)", timeoutInMsec);
	}
}

UIUtil.checkForBrokenImgLoad = function(imgId, defaultUri) {
	var img = document.getElementById(imgId);
	if (img == null || img.pzComplete == null){
		img.src = defaultUri;
	}
}

UIUtil.addServerStatusCheck = function(host) {
	// check to see if a server status check image exist already
	var imgId = "serverStatusCheck";
	var imgParentId = imgId + "Parent";
	if (document.getElementById(imgId) == null){
		document.writeln('<br/>');
		document.writeln('<span id="' + imgParentId + '"></span>');
		var serverStatusImg = document.createElement("img");
		serverStatusImg.setAttribute("id", imgId);
		serverStatusImg.setAttribute("width", 1);
		serverStatusImg.setAttribute("height", 1);
		serverStatusImg.setAttribute("src", "http://" + host + "/images/server_status_check.gif");
		UIUtil.addCheckForBrokenImg(serverStatusImg, imgId, null, 3000, true);
		document.getElementById(imgParentId).appendChild(serverStatusImg);
	}
}

UIUtil.checkServerStatus = function(imgId, isUp) {
	var serverUp = isUp;
	if (serverUp == null){
		// Safari case
		var img = document.getElementById(imgId);
		if (img == null || img.pzComplete == null){
			serverUp = false;
		} else {
			serverUp = true;
		}
	}
}

// Functions to obtain text width or height
// NOTE there is a bug in Safari that causes it not to return the proper width
// or height
UIUtil.getTextWidth = function(text, style, className) {
	return UIUtil.getTextDimensions(text, style, className, true);
}

UIUtil.getTextHeight = function(text, style, className) {
	return UIUtil.getTextDimensions(text, style, className, false);
}

UIUtil.getTextDimensions = function(text, style, className, isWidth) {
	var span = document.createElement('span');
	document.body.appendChild(span);
	span.innerHTML = text;
	if (style != null)
		UIUtil.setStyle(span, style);
	if (className != null)
		span.className = className;
	var dim = isWidth ? span.offsetWidth : span.offsetHeight;
	document.body.removeChild(span);
	return dim;
}

// Function to truncate a string containing html
// HTML tags are preserved
UIUtil.truncate = function(str, maxSize, isUnitChar, style, className) {
	if (str == "" || str == null)
		return str;
	str = new String(str);
	var elems = str.match(/<[^>]*>/g);
	var strNoElems = str.split(/<[^>]*>/);
	var strLength = isUnitChar ? strNoElems.join("").length :
			UIUtil.getTextWidth(strNoElems.join(""), style, className);
	var returnStr = new String();
	var amntRemoved = 0;
	for (var i = strNoElems.length - 1; i >= 0; i--) {
		if (strLength - amntRemoved > maxSize) {
			var words = strNoElems[i].match(/(\S+)|(\s+)/g);
			if (words != null && words.length > 0){
				for(var j = words.length - 1; j >= 0; j--) {
					if (strLength - amntRemoved > maxSize) {
						amntRemoved += isUnitChar ? words[j].length :
								UIUtil.getTextWidth(words[j], style, className);
					} else {
						returnStr = words[j] + returnStr;
					}
				}
			} else {
				amntRemoved += isUnitChar ? strNoElems[i].length :
						UIUtil.getTextWidth(strNoElems[i], style, className);;
			}
		} else {
			returnStr = strNoElems[i] + returnStr;
		}
		
		if (i > 0)
			returnStr = elems[i-1] + returnStr;
	}
	if( amntRemoved > 0)
		returnStr += "...";
	return returnStr;
}


UIUtil.ConvertHexColor = function(value, toFlash) {
	toFlash = toFlash || true;
   	return toFlash ? value.replace(/\#/, "0x") : value.replace(/0x/, "#");
}
// Fades element
function Fader(oldElem, newElem, rate) {
	this.oldElem = oldElem;
	this.newElem = newElem;
	this.rate = rate;
	this.intervalId = null;
	this.current = 100;
}

Fader.prototype.startFade = function(){
	// closure
	var self = this;
	this.oldElem.style.zIndex = 3;
	this.newElem.style.zIndex = 2;
	this.intervalId = window.setInterval(function(){self.fade();}, this.rate);
}

Fader.prototype.fade = function(){
	if (this.current > 0){
		Fader.setOpacity(this.oldElem, this.current);
		var fadeinAmnt = 100 - this.current;
		Fader.setOpacity(this.newElem, fadeinAmnt);
		this.current -= 10;
	} else {
		if(this.intervalId != null){
			Fader.setOpacity(this.oldElem, 0);
			Fader.setOpacity(this.newElem, 100);
			window.clearInterval(this.intervalId);
			this.newElem.style.zIndex = 3;
			this.oldElem.parentNode.removeChild(this.oldElem);
		}
	}
}

Fader.setOpacity = function(elem, value){
	if(UIUtil.isIE())
		elem.style.filter = "alpha(opacity:" + value + ")";
	else
		elem.style.opacity = value * 0.01;
}

// Object to parse window.location and obtain querry parameters
function UrlParser(){
	this.params = {};
	this.paramsRegExp = /[&?][^=]+\=[^&?]*/g;
	this.parse();
}

UrlParser.prototype.parse = function() {
	var queryParams = new String(window.location.search);
	if (queryParams != null && queryParams != ""){
		queryParams = queryParams.match(this.paramsRegExp);
		if (queryParams != null) {
			for (var i = 0; i < queryParams.length; i++){
				var keyVals = queryParams[i].split(/\=/);
				this.params[keyVals[0].substr(1)] = keyVals[1];
			}
		}
	}
}

// Bounding box element
function PagePosition(x, y) {
	this.x = x;
	this.y = y;
}

function BoundingBox(x, y, width, height) {
	this.x = x;
	this.y = y;
	this.width = width;
	this.height = height;
}

BoundingBox.prototype.containsPosition = function(pos, slack){
	return ((pos.x >= this.x - slack) &&
			(pos.x <= this.x + this.width + slack) &&
			(pos.y >= this.y - slack) &&
			(pos.y <= this.y + this.height + slack));
}

UIUtil.getMousePosition = function(e)
{
	if (UIUtil.isIE()) { // grab the x-y pos.s if browser is IE
		return new PagePosition(event.clientX + document.body.scrollLeft, event.clientY + document.body.scrollTop);
	} else {  // grab the x-y pos.s if browser is NS
		return new PagePosition(e.pageX, e.pageY);
	}
}
