var isIE6 = (document.compatMode != undefined && document.all != undefined && 
	document.documentElement != undefined && document.documentElement.style.maxHeight == undefined);
var isIE7 = (document.all != undefined && document.documentElement != undefined && 
	(typeof document.documentElement.style.maxHeight != "undefined"));
var isMoz = Array.every != undefined || window.Iterator != undefined;
var isSaf = (window.devicePixelRatio);

function addEvent(obj, evType, fn, useCapture){
	if (obj.addEventListener) {
		obj.addEventListener(evType, fn, useCapture);
		return true;
	} else if (obj.attachEvent) {
		var r = obj.attachEvent("on"+evType, fn);
		return r;
	} else {
		return false;
	}
}

/* << Object Prototypes */
Object.extend = function(destination, source) {
	for (property in source) {
		destination[property] = source[property];
 	}
 	return destination;
}

Object.prototype.extend = function(object) {
	return Object.extend.apply(this, [this, object]);
}

Object.prototype.clone = function (deep) {
	var objectClone = new this.constructor();
	for (var property in this)
		if (!deep) {
			objectClone[property] = this[property];
			
		} else if (typeof this[property] == "object") {
			objectClone[property] = this[property].clone(deep);
			
		} else {
			objectClone[property] = this[property];
		}
	return objectClone;
}
/* Object Prototypes >> */

/* << Date Prototypes */
var DateCompareToResult = {
	NOT_A_DATE: -1,
	EQUALS : 0,
	LESS_THAN : 1,
	GREATER_THAN : 2
}

Date.prototype.compareTo = function(toCompare){
	var result = 0;

	if (toCompare.constructor != Date) {
		result = DateCompareToResult.NOT_A_DATE;
	}
	if (result >= 0){
		if (this < toCompare) {
			result = DateCompareToResult.LESS_THAN;
			
		} else if (this > toCompare) {
			result = DateCompareToResult.GREATER_THAN;
			
		} else {
			result = DateCompareToResult.EQUALS;
		}
	}
	return result;
}

Date.prototype.toInternationalDateString = function() {
	return this.getFullYear() + "-" + _leadZero(this.getMonth() + 1) + "-" + _leadZero(this.getDate());
}
function _leadZero(v, length) {
	if (typeof(length) != "number") {
		length = 2;
	}
	v = new String(v);

	for (var i = v.length; i < length; i++) {
		v = "0" + v;
	}
	return v;
}
/* Date Prototypes >> */

/* << Number Prototypes */
Number.prototype.isPositive = function() {
	return (this >= 0) ? true : false;
}
Number.prototype.isNegative = function() {
	return (this < 0) ? true : false;
}
/* Number Prototypes >> */

/* << Function Prototypes */
Function.prototype.bind = function(object) {
	var __method = this;
	return function() {
		__method.apply(object, arguments);
	}
}
/* Function Prototypes >> */


/* << SmartAjax Class */
// TODO: This seeems to be based on prototype.js
// we can't replace it for now because we added a mechanism to handle a callback parameter
// see what can be done to avoid duplication
var SmartAjax = {
	version: "1.0"
}
SmartAjax.Request = Class.create();
SmartAjax.Request.Events = ["Uninitialized", "Loading", "Loaded", "Interactive", "Complete"];

SmartAjax.Request.prototype = {
	setOptions : function(options){
		this.options = {method: "post", asynchronous: true, parameters: ""}.extend(options || {});
	},
	
	responseIsSuccess: function() {
		return this.xmlHttp.status == undefined || 
			this.xmlHttp.status == 0 || 
			(this.xmlHttp.status >= 200 && this.xmlHttp.status < 300);
	},
	
	responseIsFailure: function() {
		return !this.responseIsSuccess();
	},
	
	initialize: function(url, options, callBackObj) {
		this.xmlHttp = new XMLHttpRequest();
		this.callBackParam = callBackObj;
		this.setOptions(options);
		if (url.length > 0) {
			this.request(url);
		}
	},
	
	request: function(url) {
		var parameters = this.options.parameters || "";
		
		if (isIE6) {
			// IE6 cache Ajax calls URL. Using a pseudo-unique URL to fool IE6.
			// See: http://stringfoo.com/2007/03/17/working-around-ie6s-caching-of-ajax-content-2
			parameters += "&_rnd="+Math.floor(Math.random() * 1001);
		}
		
		if (parameters.length > 0) {
			// According to prototype.js, it seems to fix a bug with Konqueror, Safari, KHTML browsers.
			parameters += "&_=";
		}
		
		try {
			if (this.options.method == "get") {
				url += "?" + parameters;
			}

			this.xmlHttp.open(this.options.method, url, this.options.asynchronous);

			if (this.options.asynchronous) {
				this.xmlHttp.onreadystatechange = this.onStateChange.bind(this);
				setTimeout((function() {
						this.respondToReadyState(1);
					}
				).bind(this), 10);
			}

			this.setRequestHeaders();

			var body = this.options.postBody ? this.options.postBody : parameters;
			this.xmlHttp.send(this.options.method == "post" ? body : null);
			
		} catch (ee) {/* nothing */}
	},

	setRequestHeaders: function() {
		var requestHeaders = [
			{key: "X-Requested-With", value: "XMLHttpRequest"},
			{key: "X-SmartAjax-Version", value: SmartAjax.version}
		];

		if (this.options.method == "post") {
			requestHeaders.push({key: "Content-type", value: "application/x-www-form-urlencoded"});

			/* Force "Connection: close" for Mozilla browsers to work around
			 * a bug where XMLHttpReqeuest sends an incorrect Content-length header.
			 * See Mozilla Bugzilla #246651.
			 */
			if (this.xmlHttp.overrideMimeType){
				requestHeaders.push({key: "Connection", value: "close"});
			}
		}

		if (this.options.requestHeaders) {
			requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
		}

		for (var i = 0; i < requestHeaders.length; i++) {
			this.xmlHttp.setRequestHeader(requestHeaders[i].key, requestHeaders[i].value);
		}
	},

	onStateChange : function() {
		var readyState = this.xmlHttp.readyState;
		if (readyState != 1){
			this.respondToReadyState(this.xmlHttp.readyState);
		}
	 },

	respondToReadyState : function(readyState) {
		var event = SmartAjax.Request.Events[readyState];

		if (event == "Complete") {
			(this.options['on' + this.xmlHttp.status] || 
				this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] || Prototype.emptyFunction)
			(this.xmlHttp, this.callBackParam);
		}

		(this.options['on' + event] || Prototype.emptyFunction)(this.xmlHttp, this.callBackParam);

		/* Avoid memory leak in MSIE: clean up the oncomplete event handler */
		if (event == "Complete"){
			this.xmlHttp.onreadystatechange = Prototype.emptyFunction;
		}
	}
}
/* SmartAjax Class >> */

/* << SmartMessage Class */
var SmartMessage = Class.create();
SmartMessage.defaultOptions = {
	messageTimeout : 5000,
	domId : "SmartMessage"
}

SmartMessage.extend({
	HTMLElement: null,
	timeout: null,
	display: function(message, options) {
		var displayOptions = SmartMessage.defaultOptions.clone();
		displayOptions.extend(options || {});

		clearTimeout(this.timeout);

		if (this.HTMLElement){
			this.HTMLElement.innerHTML = message;
			
		} else {
			var div = document.createElement("div");
			div.id = displayOptions.domId;
			div.innerHTML = message;
			this.HTMLElement = document.body.appendChild(div);
		}

		if (displayOptions.messageTimeout > 0){
			this.timeout = setTimeout("SmartMessage.hide()", displayOptions.messageTimeout);
		}
	},

	hide: function() {
		clearTimeout(this.timeout);
		if(this.HTMLElement){
			document.body.removeChild(this.HTMLElement);
			this.HTMLElement = null;
		}
	}
})
/* SmartMessage Class >> */

/*************************************************
	Creation of cross-browser object
	 - window.showModalDialog for Gecko
	 - XMLHttpRequest object for Internet Explorer
**************************************************/
if (!Array.prototype.push) {
	Array.prototype.push = function() {
		var startLength = this.length;
		for (var i = 0; i < arguments.length; i++) {
			this[startLength + i] = arguments[i];
		}
		return this.length;
	}
}

if (typeof(XMLHttpRequest) == "undefined") {
 	var XMLHttpRequest = function() {
		var request = null;
		try {
			request = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				request = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (ee) { /*nothing*/ }
		}
		return request;
	}
}

if (typeof(window.showModalDialog) == "undefined") {
	window.showModalDialog = function(url,arguments,features) {
		return window.open(url, arguments, toOpenParam(features));
		
		function toOpenParam(features) {
			var args = features.split(";");
			var optName = new Array();
			optName["dialogWidth"] = "width";
			optName["dialogHeight"] = "height";
			optName["dialogTop"] = "top";
			optName["dialogLeft"] = "left";
			optName["status"] = "status";
			optName["resizable"] = "resizable";
			optName["scroll"] = "scrollbars";
			var openParam = new Array();
			for (var i = 0; i < args.length; i++) {
				var arg = args[i].split(":");
				if (optName[arg[0]] != null && optName[arg[0]] != "undefined") {
					openParam[i] = optName[arg[0]].concat("=", arg[1]);
				}
			}
			openParam[openParam.length] = "modal=yes";
			return openParam.join(",");
		}
	}
}

window.location.getParameter = function(key) {
	var search = this.search.substring(1,this.search.length);
	var params = search.split("&");
	var value = new String("");
	for (var i = 0; i < params.length; i++){
		var param = params[i].split("=");
		if (param[0].toLowerCase() == key.toLowerCase()){
			value = param[1];
			break;
		}
	}
	return value;
}

window.location.searchWithoutKeys = function(keys) {
	var search = this.search.substring(1,this.search.length);
	var params = search.split("&");
	var result = new Array();
	for (var i = 0; i < params.length; i++) {
		var paramFound = false;
		
		for (var j = 0; j < keys.length; j++) {
			if (params[i].search(keys[j])) {
				paramFound = true;
				break;
			}
		}
		if (paramFound) {
			result.push(params[i]);
		}
	}
	return "?" + result.join("&");
}

function getParentTag(object, tagName) {
	var parentElement = object;
	do {
		parentElement = parentElement.parentNode;
	} while (tagName && parentElement.tagName.toLowerCase() != tagName.toLowerCase())
	return parentElement;
}