/*
 * This file is part of Nuts Framework.
 * Copyright (C) 2009 Nuts Develop Team.
 *
 * Nuts Framework is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License any later version.
 * 
 * Nuts Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
(function($) {
	var __inited = false;
	var __active = null;
	var __timer = null;

	function __emptyFn() {
	}
	
	function __init() {
		if (!__inited) {
			__inited = true;
			$('<div id="ui_popup_loader" style="display:none"></div>').appendTo('body');
			$('<div id="ui_popup_shadow" style="display:none">'
				+ ($.browser.msie && parseInt($.browser.version, 10) < 7 ?
						'<iframe src="javascript:false;" frameborder="0"></iframe>' : '')
				+ '</div>').appendTo('body');
			$('<div id="ui_popup_closer" class="ui-icon ui-icon-circle-close" style="display:none"></div>')
				.appendTo('body')
				.mousedown(__mousedown);

			$(document).mousedown(__mousedown);
			
			setInterval(__shadow, 50);
		}
	}

	function __mousedown(e) {
		if (__active && !__timer) {
			__timer = setTimeout(function() { 
				__timer = null;
				__close(e.target); 
			}, 200);
		}
	}
	
	function __shadow() {
		if (__active) {
			var p = $('#' + __active).get(0);
			$('#ui_popup_shadow').css({
				top: p.offsetTop + 'px',
				left: p.offsetLeft + 'px',
				width: p.offsetWidth + 'px',
				height: p.offsetHeight + 'px',
				display: 'block'
			}).children('iframe').css({
				width: p.firstChild.offsetWidth + 'px',
				height: p.firstChild.offsetHeight + 'px'
			});
			$('#ui_popup_closer').css({
				top: p.offsetTop - 4 + 'px',
				left: p.offsetLeft + p.offsetWidth - 12 + 'px',
				display: 'block'
			})
		}
		else {
			$('#ui_popup_shadow, #ui_popup_closer').css('display', 'none');
		}
	}

	function __close(el) {
		if (!__active || (el && el.tagName == "HTML")) {
			return;
		}

		if (el.id == 'ui_popup_closer') {
			_hide();
			return;
		}
		
		var $p = $("#" + __active), p = $p.get(0);
		var elt = $p.data('popup').trigger;

		// is self or trigger clicked?
		while (el && el.tagName != 'BODY') {
			if (el === p || el === elt || $(el).css('position') == 'absolute') {
				return;
			}
			el = el.parentNode;
		}
		
		if (el) {
			_hide({silent: true});
		}
	}
	
	function __alignTo($t, $el) {
		var p = { top: 0, left: 0 };
		if ($t.length > 0) {
			p = $t.offset();
			p.top += $t.outerHeight();
		}
	
		var bw = $.browser.width();
		var ow = $el.outerWidth();
		if (p.left + ow > bw) {
			p.left = bw - ow - 20;
			if (p.left < 0) {
				p.left = 0;
			}
		} 
	
		$el.css({
			top: p.top + "px",
			left: p.left + "px"
		});
	}
	
	function __activeTarget($t) {
		if ($t.length > 0) {
			var el = $t.get(0);
			if (el.setActive) {
				el.setActive();
			}
			else {
				el.focus();
			}
		}
	}

	function __clearTimer() {
		if (__timer) {
			clearTimeout(__timer);
			__timer = null;
		}
	}
	
	function _toggle(c) {
		c = $.extend({ id: __active }, c);
		if (!c.id) {
			return this;
		}
	
		__clearTimer();
		
		if (c.id == __active) {
			var $p = $("#" + c.id), trigger = $p.data('popup').trigger;
			if (c.trigger == trigger) {
				c.silent = true;
				_hide(c);
				return this;
			}
		}

		_show(c);
		return this;
	}

	function _show(c) {
		c = $.extend({ id: __active }, c);
		if (!c.id) {
			return this;
		}
	
		__clearTimer();

		if (c.id != __active) {
			_hide({silent: true});
		}
		
		__active = c.id;
	
		__activeTarget($(c.target || c.trigger));
	
		var $p = $("#" + c.id), $pc = $p.children(".ui-popup-content");

		if (c.url) {
			c.loaded = false;
		}

		c = $.extend($p.data('popup'), {
			silent: null,
			target: null,
			trigger: null,
			callback: null
		}, c);

		if (c.loaded) {
			__alignTo($(c.target || c.trigger), $p);
			$pc.hide().slideDown('fast');
		}
		else {
			c.show = true;
			_load(c);
		}
	}
	
	function _hide(c) {
		c = $.extend({ id: __active }, c);
		if (!c.id) {
			return;
		}
	
		__clearTimer();

		__active = null;
		__shadow();
	
		var $p = $("#" + c.id); 

		$p.css({
			top : "-999999px",
			left : "-999999px"
		});
	
		c = $.extend($p.data('popup'), {
			silent: null,
			callback: null
		}, c);

		if (c.silent != true) {
			__activeTarget($(c.target || c.trigger));
		}
	}

	function _load(c) {
		c = $.extend({ id: __active }, c);
		if (!c.id) {
			return;
		}

		if (c.show) {
			__alignTo($(c.target || c.trigger), $("#ui_popup_loader").show());
		}
	
		$.get(c.url, c.params, function(html) {
			var $p = $("#" + c.id);

			$p.data('popup').loaded = true;

			var $pc = $p.children(".ui-popup-content").html(html);

			if (c.show) {
				if ($pc.is(':hidden')) {
					$pc.show();
					__alignTo($(c.target || c.trigger), $p);
					$pc.hide().slideDown('fast');
				}
				else {
					__alignTo($(c.target || c.trigger), $p);
				}
				$("#ui_popup_loader").hide();
			}
		}, 'html');
	}
	
	function _callback(data) {
		if (__active) {
			var pd = $('#' + __active).data('popup');
			if (pd && pd.callback) {
				pd.callback(data, pd.trigger);
			}
		}
	}

	var api = {
			load: _load,
			callback: _callback,
			toggle: _toggle,
			show: _show,
			hide: _hide
		};

	$.popup = function(c) {
		__init();
		
		c = c || {};
		if (c.id) {
			var $p = $('#' + c.id);
			if ($p.length < 1) {
				$p = $('<div id="' + c.id + '" class="ui-popup">'
					+ '<div class="ui-popup-content"></div></div>').appendTo('body');
		
				$p.data('popup', c);
				if (c.content) {
					var $pc = $p.children(".ui-popup-content");
					$(c.content).detach().appendTo($pc);
					c.loaded = true;
					delete c.content;
				}
				else if (c.autoload) {
					$.get(c.url, c.params, function(html) {
						$("#" + c.id).children(".ui-popup-content").html(html)
							.data('popup').loaded = true;
					}, 'html');
				}
			}
		}

		return api; 
	};
	
	function __ontrigger() {
		$.popup().toggle($.extend({trigger: this}, $(this).data('popup')));
		return false;
	}
	
	$.fn.popup = function(c) {
		c = c || {};

		this.data('popup', c).unbind('click', __ontrigger).click(__ontrigger);
		
		return this
	};
})(jQuery);
