function defined(obj) { return typeof obj != 'undefined'; }

var WindowInfo = {};

if (window.screenLeft) {	// IE and others
	WindowInfo.getWindowX = function() { return window.screenLeft; };
	WindowInfo.getWindowY = function() { return window.screenTop; };
} else if (window.screenX) {	// Firefox and others
	WindowInfo.getWindowX = function() { return window.screenX; };
	WindowInfo.getWindowY = function() { return window.screenY; };
}

if (window.innerWidth) {	// All browsers but IE
	WindowInfo.getViewportWidth = function() { return window.innerWidth; };
	WindowInfo.getViewportHeight = function() { return window.innerHeight; };
	WindowInfo.getHorizontalScroll = function() { return window.pageXOffset; };
	WindowInfo.getVerticalScroll = function() { return window.pageYOffset; };
} else if (document.documentElement && document.documentElement.clientWidth) {
	// These functions are for IE 6 when there is a DOCTYPE
	WindowInfo.getViewportWidth = function() { return document.documentElement.clientWidth; };
	WindowInfo.getViewportHeight = function() { return document.documentElement.clientHeight; };
	WindowInfo.getHorizontalScroll = function() { return document.documentElement.scrollLeft; };
	WindowInfo.getVerticalScroll = function() { return document.documentElement.scrollTop; };
} else if (document.body && document.body.clientWidth) {
	// These are for IE4, IE5, and IE6 without a DOCTYPE
	WindowInfo.getViewportWidth = function() { return document.body.clientWidth; };
	WindowInfo.getViewportHeight = function() { return document.body.clientHeight; };
	WindowInfo.getHorizontalScroll = function() { return document.body.scrollLeft; };
	WindowInfo.getVerticalScroll = function() { return document.body.scrollTop; };
} else {
}

function onMouseOverTableRow(element, bgcolor) {
	element.style.backgroundColor = bgcolor;
}

function setBgColor(element, bgcolor) {
	if (element && element.style)
		element.style.backgroundColor = bgcolor;
}

function setMouseOverBgColors(element, color_over, color_out) {
	$(element).observe('mouseover', function(event) {
		element.style.backgroundColor = color_over;
	});
	$(element).observe('mouseout', function(event) {
		element.style.backgroundColor = color_out;
	});
}

function extendsRect(rect, x, y) {
	if (rect[0] == null || x < rect[0]) rect[0] = x;
	if (rect[1] == null || y < rect[1]) rect[1] = y;
	if (rect[2] == null || x > rect[2]) rect[2] = x;
	if (rect[3] == null || y > rect[3]) rect[3] = y;
}

function showLoadingLabel(id, label) {
	id = id || 'loading_default';
	if ($(id)) {
		var offset = document.viewport.getScrollOffsets();
		$(id).style.left = (offset[0] + (WindowInfo.getViewportWidth() - $(id).getWidth()) / 2) + "px";
		$(id).style.top = "0px";
		if (label && $(id + ":label")) $(id + ":label").update(label);
		$(id).show();
	}
}

function hideLoadingLabel(id) {
	id = id || 'loading_default';
	if ($(id)) $(id).hide();
}

function isLoadingLabelVisible(id) {
	return ($(id) && $(id).visible()) ? true : false;
}

function setCookie(name, value, duration, path, domain) {
	var expires = (duration || duration === 0) ? new Date(new Date().getTime() + duration * 1000).toGMTString() : "";
	document.cookie = name + "=" + encodeURIComponent(value) +
	                (expires ? " ;expires=" + expires : "") +
	                " ;path=" + (path ? path : "/") +
	                (domain ? " ;domain=" + domain : "");
}

function getProperStaticMapUrl(url, width, height) {
	var w = width <= 640 ? width : 640;
	var h = height <= 640 ? height : 640;
	return url.replace(/size=\d+x\d+/, "size=" + w + "x" + h);
}

function fixLat(v) {
	v = parseFloat(v);
	return v > 90 ? 90 : v < -90 ? -90 : v;
}

function fixLng(v) {
	for (v = parseFloat(v) + 180; v < 0; v += 360);
	return (v % 360) - 180;
}

function fixMBR(mbr) {
	mbr[0] = fixLat(mbr[0]);
	mbr[2] = fixLat(mbr[2]);
	mbr[1] = fixLng(mbr[1]);
	mbr[3] = fixLng(mbr[3]);
}

function encodeURIComponents(a) {
	var uri = '';
	for (var k in a)
		uri += (uri ? '&' : '') + encodeURIComponent(k) + '=' + encodeURIComponent(a[k]);
	return uri;
}

function isUrl(s) {
	var re = /^(ftp|http|https):\/\/([\w.]+:?[\w.]*@)?([\w-\.]+)(:[0-9]+)?(\/[^\s<>]*)?$/i;
	return re.test(s); 
}

function isEmail(email) {
	var re = /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/;
	return re.test(email);
}

function makeUrlLinks(str, attrs) {
	return str.replace(/((ftp|http|https):\/\/([\w.]+:?[\w.]*@)?([\w-\.]+)(:[0-9]+)?(\/[^\s<>]*)?)/gi, 
	                   "<a href=\"$1\"" + (attrs ? ' ' + attrs : '') + ">$1</a>");
}

function makeEmailLinks(str, attrs) {
	return str.replace(/([\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7})/gi, 
	                   "<a href=\"mailto:$1\"" + (attrs ? ' ' + attrs : '') + ">$1</a>");
}

function makeLinks(a, attrs) {
	if (!!(a && a.nodeType == Node.ELEMENT_NODE)) {
		if (!a.__make_links) {
			a.innerHTML = makeUrlLinks(a.innerHTML, attrs);
			a.innerHTML = makeEmailLinks(a.innerHTML, attrs);
			a.__make_links = true;
		}
	} else if (typeof a == "string") {
		makeLinks($(a), attrs);
	} else if (a && typeof a == "object" && 'splice' in a && 'join' in a) {
		a.each(function(elem) { makeLinks(elem, attrs); });
	}
}

function time(t) {
	return parseInt((t ? t : new Date()).getTime() / 1000);
}

function getRelativeTimeString(diff_seconds, trans) {
	var t = diff_seconds;
	if (!trans) trans = {};
        var end = trans['from_now'] || " from now";
	var future = false;
	if (t <= 0) {
		future = true;
		end = trans['ago'] || " ago";
		t = -t;
	}
	
	if (t < 60) {
		t = Math.round(t);
		return t + (t == 1 ? (trans['second'] || " second") : (trans['seconds'] || " seconds")) + end;
	} else if (t < 3600) {
		t = Math.round(t / 60);
		return t + (t == 1 ? (trans['minute'] || " minute") : (trans['minutes'] || " minutes")) + end;
	} else if (t < 3600 * 24) {
		t = Math.round(t / 3600);
		return t + (t == 1 ? (trans['hour'] || " hour") : (trans['hours'] || " hours")) + end;
	} else {
		d = Math.floor(t / 3600 / 24);
		h = Math.round((t - d * 3600 * 24) / 3600);
		var s = d + (d == 1 ? (trans['day'] || " day") : (trans['days'] || " days"));
		if (h > 0) s += (trans['and'] || ' and ') + h + (h == 1 ? (trans['hour'] || " hour") : (trans['hours'] || " hours"));
		return s + end;
	}
}

function getBrowserLanguage() {
	return navigator.language || navigator.userLanguage;
}

Array.prototype.contains = function(val) {
	for (var i = 0, len = this.length; i < len; i++)
		if (this[i] == val)
			return true;
	return false;
}

function extend(dst, src, override) {
	override = typeof override == 'undefined' ? true : override;
	for (var prop in src)
		if ((typeof dst[prop] == 'undefined') || override)
			dst[prop] = src[prop];
	return dst;
}

String.prototype.format = function(a) {	// args: %1, %2, %3, ...
	var pattern = /%\d+/g;
	var args = (a != null && typeof a == "object" && "splice" in a && "join" in a) ? a : arguments;
	return this.replace(pattern, function(capture) { return args[capture.match(/\d+/) - 1]; });
}

var PopupContent = {
	_list: {},
	init: function(anchor_id, content_id, type, pos) {
		var anchor = $(anchor_id);
		var content = $(content_id);
		if (!anchor || !content) return;
		
		content.popup_content = {pos: pos.split('-'), type: type, anchor: anchor_id};
		content.style.left = content.style.top = 0;

		if (!type || type == 'mouseover') {
			anchor.observe('mouseover', function(e) { PopupContent.show(this, content, e); });
			anchor.observe('mouseout', function(e) { PopupContent.hide(this, content, e); });
			content.observe('mouseout', function(e) { PopupContent.hide(this, content, e); });
		}
		anchor.observe('click', function(e) { PopupContent.show(this, content, e); return false; });

		this._list[content_id] = {type: type, pos: pos, obj: content, anchor: anchor_id};
	},
	show: function(anchor, content, e) {
		if (e.type == 'click' && content.visible()) {
			content.hide();
			return;
		}
		for (id in this._list) {
			if (content.id != id && $(id)) $(id).hide();
		}
		
		var viewoffset = anchor.viewportOffset();
		var scrolloffset = document.viewport.getScrollOffsets();
		var left = viewoffset[0] + scrolloffset[0] + (content.popup_content.pos[0] == 'right' ? anchor.getWidth() - content.getWidth() : 0);
		var top = viewoffset[1] + scrolloffset[1] + (content.popup_content.pos[1] == 'top' ? -content.getHeight() : anchor.getHeight());
		content.style.left = left + "px";
		content.style.top = top + "px";		
		content.show();
	},
	hide: function(ref, content, e) {
		if (!content.visible() ||
		    $(e.target).tagName.toUpperCase() == 'OPTION' || 
		    $(e.target).descendantOf(content))
			return;
		var x = e.pointerX(), y = e.pointerY();
		if (!this._contains(ref, x, y) && !this._contains(content, x, y))
			content.hide();
	},
	hideAll: function() {
		for (id in PopupContent._list) {
			var obj = PopupContent._list[id].obj;
			if (obj.visible()) obj.hide();
		}
	},
	_contains: function(obj, x, y) {
		var offset = [0, 0];
		if (obj.style.position.toUpperCase() == 'ABSOLUTE') {
			offset = obj.positionedOffset();
		} else {
			offset = obj.viewportOffset();
			var scrolloffset = document.viewport.getScrollOffsets();
			offset[0] += scrolloffset[0]; offset[1] += scrolloffset[1];
		}
		return (x < offset[0] || y < offset[1] || x >= (offset[0] + obj.getWidth()) || y >= (offset[1] + obj.getHeight())) ? false : true;
	},
	_clickHandler: function(e) {
		var x = e.pointerX(), y = e.pointerY();
		for (id in PopupContent._list) {
			var obj = PopupContent._list[id].obj;
			if (!obj.visible()) continue;
			PopupContent.hide($(PopupContent._list[id].anchor), obj, e);
		}
	}
};

(function() {
	document.stopObserving("mousedown", PopupContent._clickHandler);
	document.observe("mousedown", PopupContent._clickHandler);
})();

