/**
 * Class to handle popups.
 */
module.exports = new Class
({
	Extends: Vn.Component
	,Tag: 'htk-popup'
	,Properties:
	{
		/**
		 * The popup child.
		 */
		child:
		{ 
			type: Vn.Component
			,set: function (x)
			{
				this._child = x;
				this._setChildNode (x.node);
			}
			,get: function ()
			{
				return this._child;
			}
		}
		/**
		 * The popup child Node.
		 */
		,childNode:
		{ 
			type: Object
			,set: function (x)
			{
				this._child = null;
				this._setChildNode (x);
			}
			,get: function ()
			{
				return this.node.firstChild;
			}
		}
		/**
		 * Indicates how the dialog must be displayed.
		 */
		,modal:
		{ 
			type: Boolean
			,set: function (x)
			{
				this._modal = x;
			}
			,get: function ()
			{
				return this._modal;
			}
		}
	}

	,_parent: null
	,_fitParent: false
	,_modal: false
	,_isOpen: false
	,_child: null

	,initialize: function (props)
	{
		this._bgMouseDownHandler = this._bgMouseDown.bind (this);
		this._bgKeyPressHandler = this._bgKeyPress.bind (this);
		this.parent (props);
	}
	
	,render: function ()
	{
		var div = this.createRoot ('div');
		div.className = 'htk-popup';
	}

	,_setChildNode: function (childNode)
	{
		Vn.Node.removeChilds (this.node);
		this.node.appendChild (childNode);
	}

	/**
	 * Shows the popup relative to another element.
	 *
	 * @param {Node} parent The relative element
	 * @param {boolean} fitParent Wether to set the width same to the parent
	 * @param {HTMLEvent} ignoreEvent An optional event object to ignore
	 */
	,show: function (parent, fitParent, ignoreEvent)
	{
		this._parent = parent;
		this._fitParent = fitParent;
		this.open (ignoreEvent);
	}
	
	/**
	 * Opens the popup.
	 *
	 * @param {Node} parent The relative element
	 * @param {boolean} fitParent Wether to set the width same to the parent
	 */
	,open: function (ignoreEvent)
	{
		if (ignoreEvent)
			this._ignoreEvent = ignoreEvent;

		if (this._isOpen)
		{
			this.resetAsync ();
			return;
		}

		var node = this.node;
	
		node.addEventListener ('mousedown', this._onPopupMouseDown.bind (this));
		this.doc.addEventListener ('keypress', this._bgKeyPressHandler);

		if (this.isModal ())
		{
			var bg = this._bg = this.createElement ('div');
			bg.className = 'htk-background';
			bg.addEventListener ('mousedown', this._bgMouseDownHandler);
			Htk.Toast.pushTop (bg);

			Vn.Node.addClass (node, 'modal');
			bg.appendChild (node);

			this.doc.body.appendChild (bg);
		}
		else
		{
			this.doc.addEventListener ('mousedown', this._bgMouseDownHandler);
			this.doc.body.appendChild (node);
			Vn.Node.addClass (node, 'fixed');
			this.resetAsync ();
		}

		setTimeout (this._onOpacityTimeout.bind (this), 10);
		this._isOpen = true;
	}

	/**
	 * Returns if the popup window shoud be modal based on the modal property
	 * and if the device is mobile.
	 *
	 * @return {boolean} %true if it's modal, %false otherwise
	 */
	,isModal: function ()
	{
		return this._modal || Vn.isMobile () || !this._parent;
	}
	
	,_onOpacityTimeout: function ()
	{
		if (!this._isOpen)
			return;

		if (this._bg)
			this._bg.style.opacity = 1;
		
		this._node.style.opacity = 1;
	}

	,_onResetTimeout: function ()
	{
		this.reset ();
	}

	,resetAsync: function ()
	{
		setTimeout (this._onResetTimeout.bind (this));
	}
	
	/**
	 * Repositions the popup.
	 */
	,reset: function ()
	{
		if (!this._isOpen || this.isModal ())
			return;

		var node = this._node;

		var style = node.style;
		style.visibility = 'hidden';
		style.height = '';
		style.width = '';

		var margin = 20;
		var dblMargin = margin * 2;
	
		var iniWidth;
		var iniHeight;
		var width = iniWidth = node.offsetWidth;
		var height = iniHeight = node.offsetHeight;

		var windowWidth = window.innerWidth;
		var windowHeight = window.innerHeight;

		if (width + dblMargin > windowWidth)
			width = windowWidth - dblMargin;
		if (height + dblMargin > windowHeight)
			height = windowHeight - dblMargin;

		var rect = this._parent.getBoundingClientRect ();
		var left = rect.left;
		var top = rect.top + this._parent.offsetHeight;

		if (this._fitParent)
			width = this._parent.offsetWidth;

		if (left + width + margin > windowWidth)
			left -= (left + width) - window.windowWidth + margin;
		if (top + height + margin > windowHeight)
			top -= height + this._parent.offsetHeight;

		if (left < margin)
			left = margin;
		if (top < margin)
			top = margin;

		style.top = (top) +'px';
		style.left = (left) +'px';

		if (width != iniWidth)
			style.width = (width) +'px';
		if (height != iniHeight)
			style.height = (height) +'px';

		style.visibility = 'initial';
	}

	/**
	 * Hides the popup.
	 */
	,hide: function ()
	{
		if (!this._isOpen)
			return;

		var node = this._node;

		if (this._bg)		
		{
			Htk.Toast.popTop ();
			Vn.Node.remove (this._bg);
			Vn.Node.removeClass (node, 'modal');
			this._bg = null;
		}
		else
		{
			this.doc.removeEventListener ('mousedown', this._bgMouseDownHandler);
			Vn.Node.removeClass (node, 'fixed');
		}

		Vn.Node.remove (node);
		this._parent = null;
		this._isOpen = false;
		this.emit ('closed');
	}
	
	,_bgMouseDown: function (e)
	{
		if (e !== this._ignoreEvent)
			this.hide ();
			
		this._ignoreEvent = null;
	}

	,_bgKeyPress: function (e)
	{
		if (e.keyCode == 27) // Escape
			this.hide ();
	}
	
	,_onPopupMouseDown: function (e)
	{
		this._ignoreEvent = e;
	}
});

