liwe.lightbox = {};

// {{{ base docs
/**
Lightbox
========

Lightbox is a class aimed to display temporary modal forms to the user.

Lightbox is a *static* class, you don't have to instantiate it by yourself in your code.
You can access it with ``liwe.lightbox`` static class.

Lightbox requesters are stacked like a pile one over the other. You can programmatically create any number of lightboxes and the most recent one will always be visible over
all the previous lightboxes created.

You can only remove the top lightbox on the stack, using the ``liwe.lightbox.close()`` method.

.. warning:: 
	``lightbox.events`` not documented yet

*/
// }}}


liwe.lightbox.opacity = 70;
liwe.lightbox.fade = false;
liwe.lightbox._is_show = false;

liwe.lightbox._back_div  = null;
liwe.lightbox._front_div = [];

liwe.lightbox._max_zindex  = null;
liwe.lightbox._max_zindex_el  = 'div';

liwe.lightbox.events = {
	"click" : null,
	"close" : null
};

// {{{ liwe.lightbox.create ( id, w, h, x, y )
/**
.. function:: liwe.lightbox.create ( id, w, h, [ x, [ y ] ] )

	Creates a new lightbox area.

	:param id: the new lightbox id. This id can then be used to modify lightbox content. This field is mandatory.
	:param w:  lightbox width (in pixels). This field is mandatory.
	:param h:  lightbox height (in pixels). This field is mandatory.
	:param x:  lightbox x position (in pixels) This field is optional. If not passed the lightbox x position
		   will be computed to put the lightbox in the middle of the screen.

	:param y:  lightbox y position (in pixels). This field is optional. If not passed the lightbox y position
		   will be computed to put the lightbox in the middle of the screen.

	:rtype: this function returns nothing.
*/
liwe.lightbox.create = function ( id, w, h, x, y )
{
	var back = liwe.lightbox._add_back_div ();
	var div  = liwe.lightbox._add_front_div ( id, w, h, x, y );

	return div;
};
// }}}
// {{{ liwe.lightbox.created ()
/**
.. function:: liwe.lightbox.created ()

	This function simply checks if at least one lightbox is currently shown on the screen.
	This function returns ``true`` if there is at least one lightbox currently shows, ``false`` otherwise.

	:rtype: returns ``true`` if there is at least one lightbox currently shows, ``false`` otherwise.
*/
liwe.lightbox.created = function ()
{
	return liwe.lightbox._back_div != null;
};
// }}}
// {{{ liwe.lightbox.close ()
/**
.. function:: liwe.lightbox.close ()

	This function closes the topmost lightbox currenlty shown on the browser window.
*/
liwe.lightbox.close = function ()
{
	var d;

	d = liwe.lightbox._front_div.pop ();
	liwe.dom.remove_element ( d );

	if ( liwe.lightbox.events [ 'close' ] ) liwe.lightbox.events [ 'close' ] ();

	liwe.dom.remove_element ( liwe.lightbox._back_div );
	liwe.lightbox._back_div = null;
};
// }}}
// {{{ liwe.lightbox.show ()
/**
.. function:: liwe.lightnox.show ()

	This function shows on browser window the last created lightbox.
*/
liwe.lightbox.show = function ()
{
	var div = liwe.lightbox._front_div [ liwe.lightbox._front_div.length -1 ];

	liwe.fx.set_opacity ( liwe.lightbox._back_div, liwe.lightbox.opacity );
	liwe.lightbox._back_div.style.display = "block";

	if ( liwe.lightbox.fade )
	{
		div.style.display = "block";

		liwe.fx.fade_in ( div );
	} else 
		liwe.fx.set_opacity ( div, 100 );
};
// }}}
// {{{ liwe.lightbox.easy ( id, title, w, h, x, y )
/**
.. function:: liwe.lightnox.easy ( id, title, w, h, x, y )

	This is a commodity function that will call the ``liwe.lightbox.create()`` method to build a new lightbox,
	sets a custom layout (with a close button on the upper right corner of the lightbox screen) and then calls
	the ``liwe.lightbox.show()`` to show it to the user.

	:param id: the new lightbox id. This id can then be used to modify lightbox content. This field is mandatory.
	:param title: the lightbox title that will be shown on the window bar.
	:param w:  lightbox width (in pixels). This field is mandatory.
	:param h:  lightbox height (in pixels). This field is mandatory.
	:param x:  lightbox x position (in pixels) This field is optional. If not passed the lightbox x position
		   will be computed to put the lightbox in the middle of the screen.

	:param y:  lightbox y position (in pixels). This field is optional. If not passed the lightbox y position
		   will be computed to put the lightbox in the middle of the screen.

	:rtype: this function returns nothing.
*/
liwe.lightbox.easy = function ( id, title, w, h, x, y )
{
	var div = liwe.lightbox.create ( id + "_win", w, h, x, y );
	var s;

	div.className = "lightbox_easy";
	if ( liwe.lightbox.fade ) liwe.fx.set_opacity ( div, 0 );

	s  = '<div class="title">' + title;
	s += '<div class="close" onclick="liwe.lightbox.close()"></div></div><div id="' + id + '"></div>';

	div.innerHTML = s;

	// TODO: fare il "pallino"

	liwe.lightbox.show ();
};
// }}}

// PRIVATE METHODS

// {{{ liwe.lightbox._add_back_div ()
liwe.lightbox._add_back_div = function ()
{
	var d = liwe.lightbox._back_div;
	var max_zindex = ( ! liwe.lightbox._max_zindex ) ? liwe.lightbox._get_highest_zindex () : liwe.lightbox._max_zindex;
	
	if ( ! d ) 
	{
		d = liwe.dom.create_element ( "div", "liwe_lightbox" );

		d.style.display = 'none';
		d.style.backgroundColor = "black";

		liwe.lightbox._back_div = d;
	}

	d.style.zIndex = max_zindex + 10;
	d.style.top = 0;
	d.style.left = 0;
	if ( liwe.utils.supports ( 'transition' ) )
	{
		d.style.bottom = 0;
		d.style.right = 0;
	} else {
		var size = liwe.lightbox._get_size ();
		d.style.width  = size.bw + "px"; // "100%";
		d.style.height = size.bh + "px";
	}
	d.style.position = "fixed"; // "absolute";

	liwe.events.add ( d, "click", liwe.lightbox._back_click );

	return d;
};
// }}}
// {{{ liwe.lightbox._back_click ()
liwe.lightbox._back_click = function ()
{
	if ( liwe.lightbox.events [ 'click' ] ) liwe.lightbox.events [ 'click' ] ();
};
// }}}
// {{{ liwe.lightbox._add_front_div ( idm wm h, x, y )
liwe.lightbox._add_front_div = function ( id, w, h, x, y )
{
	var d = liwe.lightbox._back_div;
	var div = liwe.dom.create_element ( "div", id );
	var max_zindex = ( ! liwe.lightbox._max_zindex ) ? liwe.lightbox._get_highest_zindex () + 1 : liwe.lightbox._max_zindex;
	var res, r, b;

	y = ( ! y ) ? 10 : y;

	if ( w == 'auto' )
	{
		x = 10;
		r = 10;
	}

	if ( h == 'auto' )
	{
		b = 10;
	}

	if ( !b && !r )
	{
		w += 80;
		h += 80;

		res = this._calc_size ( w, h, x, y );

		w = res [ 0 ];
		h = res [ 1 ];
		x = res [ 2 ];
		y = res [ 3 ];
	}

	div.style.zIndex = max_zindex + 5;
	div.style.width  = w + "px";
	div.style.height = h + "px";
	div.style.left = x + "px";
	if ( r ) div.style.right = r + "px";
	if ( b ) div.style.bottom = b + "px";
	//div.style.top  = y + "px";
	div.style.top  = y + "px";
	div.style.position = "absolute"; //"fixed";

	liwe.lightbox._front_div.push ( div ); // = div;
	liwe.lightbox._front_div_id = id; 

	return div;
};
// }}}
// {{{ liwe.lightbox.set_size ( w, h, x, y )
liwe.lightbox.set_size = function ( w, h, x, y )
{
	var res;
	var div = document.getElementById ( liwe.lightbox._front_div_id );

	if ( ! div ) 
	{
		console.warning ( "Could not find DIV: %s", liwe.lightbox._front_div_id );
		return;
	}

	res = this._calc_size ( w, h, x, y );

	w = res [ 0 ];
	h = res [ 1 ];
	x = res [ 2 ];
	y = res [ 3 ];

	div.style.width  = w + "px";
	div.style.height = h + "px";
	div.style.left = x + "px";
	div.style.top  = y + "px";
};
// }}}
// {{{ liwe.lightbox._get_size ()
liwe.lightbox._get_size = function ()
{

	var bw, bh, sh, sw, ih, iw;
	var D = document;

	bh = Math.max (
		Math.max ( D.body.offsetHeight, D.documentElement.offsetHeight ),
		Math.max ( D.body.clientHeight, D.documentElement.clientHeight )
		//,window.innerHeight
	);

	bw = Math.max (
		Math.max ( D.body.offsetWidth, D.documentElement.offsetWidth ),
		Math.max ( D.body.clientWidth, D.documentElement.clientWidth )
		//, window.innerWidth
	);

	/*
	sh = Math.max ( Math.max ( D.body.scrollHeight, D.documentElement.scrollHeight ), bh );
	sw = Math.max ( Math.max ( D.body.scrollWidth, D.documentElement.scrollWidth ), bw );
	*/
	ih = ( window.innerHeight ) ? window.innerHeight : D.documentElement.clientHeight;
	iw = ( window.innerHeight ) ? window.innerWidth : D.documentElement.clientWidth;

	sh = Math.max ( D.body.scrollTop, D.documentElement.scrollTop );

	console.debug ( "Get Size: bw: " + bw + " - " + bh + " - iw: " + iw + " - " + ih );

	return { 'bh' : bh, 'bw' : bw, 'sh' : sh, 'iw' : iw, 'ih' : ih };
};
// }}}
// {{{ liwe.lightbox._calc_size = function ( w, h, x, y )
liwe.lightbox._calc_size = function ( w, h, x, y )
{
	var size = liwe.lightbox._get_size () ;

	if ( ! w ) w = 0;
	if ( ! h ) h = 0;
	if ( ! x ) x = 0;
	if ( ! y ) y = 0;

	//y = size.sh + 5;
	x = Math.abs ( size.bw - w ) / 2;
	y = size.sh + 10;

	var margin_h = size.ih; // size.bh;
	if ( margin_h > h )
 		y = Math.abs ( ( ( margin_h - h ) / 2 ) + size.sh );
	//FIXME: y fissa per testing
	//y = 10;
	return [ w, h, x, y ];
};
// }}}
// {{{ liwe.lightbox._get_highest_zindex = function ()
liwe.lightbox._get_highest_zindex = function ()
{
	var el = liwe.lightbox._max_zindex_el;
	var z = 0, tmp, val;
	var elems = document.getElementsByTagName ( el );
	for ( var c = 0; c < elems.length; c++ )
			{
				//if ( document.defaultView ) val = document.defaultView.getComputedStyle ( elems[c], null ).getPropertyValue ( 'z-index' );
				if ( elems [ c ].currentStyle ) val = elems [ c ].currentStyle [ 'zIndex' ];
				if ( window.getComputedStyle ) val = window.getComputedStyle ( elems[c], null ).getPropertyValue ( 'z-index' );

				tmp = parseInt ( val, 10 );
			
				if ( ( ! isNaN ( tmp ) ) && ( tmp  > z ) ) z = tmp;
			} 
	return z;
};
// }}}

