/**
 * @author bradleyc
 * @requires GSI.Dimensions, GSI.Browser
 * @constructor
 */
GSI.Position = function(){}
GSI.NameSpace.create("GSI.Position");

/** 
 * An array of elements that have been made "fixed" positioning
 * @private
 * @type Array
 */
GSI.Position.fixedElements = [];

/**
 * An array of elements that have been vertically centered
 * @private
 * @type Array
 */
GSI.Position.vCenterElements = [];

/**
 * An array of elements that have been horizontally centered
 * @private
 * @type Array
 */
GSI.Position.hCenterElements = [];

/** 
 * A boolean flag to test if event listeners have been created
 * @private
 * @type Boolean
 */
GSI.Position.observing = false;

/**
 * Center an element horizontally to window
 * @param {Object} el		The element to position
 */
GSI.Position.hCenterWindow = function( el )
{
	el = $(el);
	if( this.hCenterElements.indexOf(el) > -1 )	return;
	this.hCenterElements.push(el);
	if( !this.observing ) this.createEventListeners();
	this.recenter();
}

/**
 * Center an element vertically to the window
 * @param {Object} el		The element to position
 */
GSI.Position.vCenterWindow = function( el )
{
	el = $(el);
	if( this.vCenterElements.indexOf(el) > -1 ) return;
	this.vCenterElements.push(el);
	if( !this.observing ) this.createEventListeners();
	this.recenter();
}

/**
 * Keep an object positioned relative to the top of the screen
 * @param {Object} el
 * @deprecated
 */
GSI.Position.keepTop = function(el)
{
	this.makeFixed(el, {top: 0});
}

/**
 * Make element use fixed position.
 * This checks to see if the browser is IE and if so,
 * creates event listeners to reposition the div as if it were fixed
 * @param {Element} el
 * @param {Object} pos 	An object with top,bottom,left,right as properties (no "px")
 **/
GSI.Position.makeFixed = function( el, pos )
{	
	if( this.fixedElements.indexOf(el) > -1 ) return;
	el = $(el);

//	If this isn't IE just set position to fixed and return
	if( !GSI.Browser.is("IE") )
	{
		if( !isNaN(pos.top) ) pos.top = parseInt(pos.top)+"px";
		if( !isNaN(pos.right) ) pos.right = parseInt(pos.right)+"px";
		if( !isNaN(pos.bottom) ) pos.bottom = parseInt(pos.bottom)+"px";
		if( !isNaN(pos.left) ) pos.left = parseInt(pos.left)+"px";
		pos.position = "fixed";
		
		Element.setStyle( el, pos );
		return;
	}
	
//	Get the position data for the element	
	var positionData = pos ||
	{
		top: this.get(el,"top"),
		right: this.get(el,"right"),
		bottom: this.get(el,"bottom"),
		left: this.get(el,"left")
	}

//	Check for positioning
	el.setStyle({position: "absolute"});
	el.originalPosition = positionData;
	this.fixedElements.push(el);
	this.reposition();
}

/**
 * Create the event listeners used by this namespace
 * @private
 */
GSI.Position.createEventListeners = function()
{
	if( this.observing ) return;
	
	Event.observe( window, "resize", this.reposition.bindAsEventListener(this) );
	Event.observe( window, "scroll", this.reposition.bindAsEventListener(this) );
	
	Event.observe( window, "resize", this.recenter.bindAsEventListener(this) );
	Event.observe( window, "scroll", this.recenter.bindAsEventListener(this) );
	
	this.observing = true;
}

/**
 * Re-center an element within the viewport.
 * Called automatically from event listener, there should be no need
 * to call this manually.
 * @private
 */
GSI.Position.recenter = function()
{
	var el;
	var scrollPos = GSI.Dimensions.getScrollOffset();
	var windowSize = GSI.Dimensions.getWindowSize();
	
//	Horizontal centering
	for( var i=0, len=this.hCenterElements.length; i<len; i++ )
	{
		el = $(this.hCenterElements[i]);
		Element.setStyle( el, {left: (( windowSize.width - el.getWidth() ) / 2 ) + scrollPos.xOffset + "px" } );
	}

//	Vertical centering
	for( var i=0, len=this.vCenterElements.length; i<len; i++ )
	{
		el = $(this.vCenterElements[i]);
		Element.setStyle( el, {top: (( windowSize.height - el.getHeight() ) / 2 ) + scrollPos.yOffset + "px" } );
	}
}

/**
 * Reposition an element within the viewport.
 * Called automatically from event listener, there should be no need
 * to call this manually.
 * @private
 */
GSI.Position.reposition = function()
{
	var el;
	var scrollPos = GSI.Dimensions.getScrollOffset();
	var windowSize = GSI.Dimensions.getWindowSize();
	var bodySize = GSI.Dimensions.getBodySize();
	
	var newStyle = {};
	var elPos;
	var val;
	
	for( var i=0,len=this.fixedElements.length;i<len;i++ )
	{
		el = $(this.fixedElements[i]);
		elPos = el.originalPosition;
		newStyle = {};
		if( typeof elPos.top == 'number' )
		{
			val = ( scrollPos.yOffset + elPos.top );
			newStyle.top = val + "px";
		}
		if( typeof elPos.right == 'number' )
		{
			val = elPos.right; 
			if( scrollPos.xOffset > 0 ) val = elPos.right - scrollPos.xOffset;
			newStyle.right = val + "px";
		}
		if( typeof elPos.bottom == 'number' )
		{
			val = elPos.bottom; 
			if( scrollPos.yOffset > 0 ) val = elPos.bottom - scrollPos.yOffset;
			newStyle.bottom = val + "px";
		}
		if( typeof elPos.left == 'number' )
		{
			val = ( scrollPos.xOffset + elPos.left );
			newStyle.left = val + "px";
		}
		
		Element.setStyle( el, newStyle );
	}
	
}

/**
 * Get the position of an element
 * @param {String} side		"top","bottom", etc
 * @return Value for the position of the element or undefined
 * @type Number
 **/
GSI.Position.get = function( el, side )
{
	var p = Element.getStyle(el,side);
	if( p == undefined || p == null ) return undefined;
	return parseInt(p);
}

/**
 * Keep an object at the top left of the screen
 * @param {Object} el	The element to position
 * @deprecated
 */
GSI.Position.keepTopLeft = function( el )
{
	this.makeFixed(el, {top:0,left:0});
}

GSI.Position.createEventListeners();