//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Box functions
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

var zxBaseBox = zxBaseClass.extend (
{
	///////////////////////////////////////////////////////////////////////////////////////////////
	// PUBLIC
	///////////////////////////////////////////////////////////////////////////////////////////////

	initialize: function()
	{
		this.parent();
		
		this._transitionShowOptions = { duration: 750, transition: Fx.Transitions.cubicOut, onComplete: this.onShowEnd };
		this._transitionHideOptions = { duration: 100, transition: Fx.Transitions.cubicOut };

		// create nodes for input and background div
		this._divNode = new Element( 'div' );
		this._divNode.setStyle( 'display', 'none' );
		this._divNode.setStyle( 'visibility', 'hidden' );
		this._divNode.setStyle( 'position', 'absolute' );
		this._divNode.setStyle( 'width', '1px' );
		this._divNode.addClass( 'baseBox' );

		this._divBackgroundNode = new Element( 'div' );
		this._divBackgroundNode.setStyle( 'display', 'none' );
		this._divBackgroundNode.setStyle( 'position', 'absolute' );
		this._divBackgroundNode.addClass( 'baseBoxBackground' );
		
		this._contentNode = null;
		this._contentNodeLastCssPosition = null;
		this._contentNodeParentNode = null;

		this._bodyNode = $E( 'body' );
		
		// inject divs used by this box into document
		this._divBackgroundNode.injectInside( this._bodyNode );
		this._divNode.injectInside( this._bodyNode );
	},

	show: function( width, contentNode )
	{
		if ( contentNode == null ) return;

		width = $pick( width, 200 );

		// eigther node was passed or id of node
		if ( typeof(contentNode) == 'string' )
		{
			this._contentNode = $( contentNode );
		}
		else
		{
			this._contentNode = contentNode;
		}
		
		// save parent node of content node to display to restore position later on unhide
		this._contentParentNode = this._contentNode.parentNode;
		
		// save css data from content node to restore it later		
		this._contentNodeLastCssPosition = this._contentNode.getStyle( 'position' );

		// object content node into box div
		this._contentNode.injectInside( this._divNode );

		// set position and size of background to fit whole page
		this._setBackgroundPosition();

		// pre show phase (content is still hidden because of visibility = hidden)
		this._contentNode.setStyle( 'display', 'block' );
		this._contentNode.setStyle( 'position', 'static' );
		this._divNode.setStyle( 'display', 'block' ); 

		// postioning and sizing phase
		
		this._setPositions( width );

		// final show phase with fade, first background, than content
		this._divBackgroundNode.setStyle( 'display', 'block' ); 
	
		this.onShowBegin();
		
		var divNodeShow = new Fx.Styles( this._divNode, this._transitionShowOptions );
		divNodeShow.start( { 'opacity' : [0,1] } );
	},
	
	
	hide: function()
	{
		this._transitionHideOptions.onComplete = function()
			{
				// hide background 
				this._divBackgroundNode.setStyle( 'display', 'none' ); 

				// and content finally if transition is complete
				this._divNode.setStyle( 'display', 'none' ); 
				
				if ( this._contentNode == null ) return;
				
				this._contentNode.setStyle( 'display', 'none' );
				this._contentNode.setStyle( 'position', this._contentNodeLastCssPosition );
		
				// restore position of shown content node to previous one
				if ( this._contentParentNode != null )
				{
					this._contentNode.injectInside( this._contentParentNode );
				}
				else
				{
					this._contentNode.injectInside( this._bodyNode );
				}

				this.onHideEnd();
				
			}.bind(this);
		

		this.onShowBegin();

		// final hide phase with fader
		var divNodeShow = new Fx.Styles( this._divNode, this._transitionHideOptions );
		divNodeShow.start( { 'opacity' : [1,0] } );
	},
	
	center: function()
	{
		this._setPositions( null );
	},


	///////////////////////////////////////////////////////////////////////////////////////////////
	// OVERRIDABLE
	///////////////////////////////////////////////////////////////////////////////////////////////
	
	onShowBegin: function()
	{
		this.fireEvent( 'onShowBegin' );
	},

	onShowEnd: function()
	{
		this.fireEvent( 'onShowEnd' );
	},

	onHideBegin: function()
	{
		this.fireEvent( 'onHideBegin' );
	},

	onHideEnd: function()
	{
		this.fireEvent( 'onHideEnd' );
	},
	
	_setBackgroundPosition: function()
	{
		// get required size positions
		var sizes = this.getPageSizeInfos();
		var pageWidth = sizes.pageWidth;
		var pageHeight = sizes.pageHeight;
		var windowWidth = sizes.windowWidth;
		var windowHeight = sizes.windowHeight;
		var scrollTop = window.getScrollTop();
		var scrollLeft = window.getScrollLeft();

		this._divBackgroundNode.setStyle( 'top', 0 ); 
		this._divBackgroundNode.setStyle( 'left', 0 ); 

		this._divBackgroundNode.setStyle( 'width', pageWidth ); 
		this._divBackgroundNode.setStyle( 'height', pageHeight ); 
	},

	_setPositions: function( width )
	{
		// get required size positions
		var sizes = this.getPageSizeInfos();
		var pageWidth = sizes.pageWidth;
		var pageHeight = sizes.pageHeight;
		var windowWidth = sizes.windowWidth;
		var windowHeight = sizes.windowHeight;
		var scrollTop = window.getScrollTop();
		var scrollLeft = window.getScrollLeft();

		// determine width automatically if no width specified
		if ( width == null ) width = this._divNode.getSize().size.x;
		
		// get position
		height = this._divNode.getSize().size.y;

		this._divNode.setStyle( 'width', width ); 

		this._divNode.setStyle( 'top', (windowHeight/2 - height/2) + scrollTop ); 
		this._divNode.setStyle( 'left', (windowWidth/2 - width/2) + scrollLeft ); 
	}

});
