/**
* AnchoredPopupOpenCommand
*
* @param a The AnchoredPopupComponent to open
**/
function AnchoredPopupOpenCommand( a ) {

	this.popup_to_open = a;
	
}

new AnchoredPopupOpenCommand();

AnchoredPopupOpenCommand.prototype.execute = function() { 

	this.popup_to_open.openPopup();

}

/**
* AnchoredPopupCloseCommand
*
* @param a The AnchoredPopupComponent to close
**/
function AnchoredPopupCloseCommand( a ) { 

	this.popup_to_open = a;

}

new AnchoredPopupCloseCommand();

AnchoredPopupCloseCommand.prototype.execute = function() { 

	this.popup_to_open.closePopup();

}

/**
* Class AnchoredPopupComponent
*
* A component decorator.  Adds the functionality of allowing the component to be anchored to a side of the 
* browser window and pop up when the "tab" is clicked
*
* @param c The contained Component
* @param style_set
*   -style_set-apc_container
*   -  style_set-apc_sbw_out
*   -  style_set-apc_sbw_out_container
*   -  style_set-apc_sbw_over
*   -  style_set-apc_sbw_over_container
* @param side The side of the browser window to attach the element
* @param offset The offset of the element from the top when attached to the left or right or the left when attached to the top or bottom
* @param ae The animation engine to use when animating the popup.  If no animation engine is provided, the 
*    AnchoredPopupComponent simply pops up and down without flowing movement
**/
function AnchoredPopupComponent( c, style_set, side, offset, ae, open_text, close_text ) { 

	this.state = "closed";

	this.contained_component = c;
	this.style_set = style_set + "_apc";
	this.side = side || "top";
	this.offset = parseInt( offset );
	this.ae = ae || false;

	this.container = document.createElement( 'div' );
	this.container.className = this.style_set + "_container";

	this.accordion = document.createElement( 'div' );
	this.accordion.style.overflow = "hidden";

	this.open_tab = new SimpleButtonWidgetFactory( this.style_set + "_closed", new AnchoredPopupOpenCommand( this ) ).build();
	this.close_tab = new SimpleButtonWidgetFactory( this.style_set + "_open", new AnchoredPopupCloseCommand( this ) ).build();

	if ( open_text ) { 
		this.open_tab.addContentNode( textToDOM( 'span', open_text, this.style_set ) );
	}
	if ( close_text ) { 
		this.close_tab.addContentNode( textToDOM( 'span', close_text, this.style_set ) );
	}

	this.accordion.appendChild( this.contained_component.getWidgetDOM() );

	//build the popup
	switch( this.side ) {
		case "top":
			this.container.appendChild( this.accordion );
			this.container.appendChild( this.open_tab.getWidgetDOM() );
			this.container.appendChild( this.close_tab.getWidgetDOM() );
			this.vertical_open_direction = 1;
			this.horizontal_open_direction = 0;
			this.accordion.style.height = "1px";
			break;
		case "bottom":
			this.container.appendChild( this.open_tab.getWidgetDOM() );
			this.container.appendChild( this.close_tab.getWidgetDOM() );
			this.container.appendChild( this.accordion );
			this.vertical_open_direction = -1;
			this.horizontal_open_direction = 0;
			this.accordion.style.height = "1px";
			break;
		default: 
			throw( "AnchoredPopupComponent :: Invalid side parameter of " + side + " found." );
			break;
	}

	this.close_tab.hideWidget();

	this.container.style.position = 'absolute';

}

/**
* AnchoredPopupComponent.getSide
*
* @returns side string
**/
AnchoredPopupComponent.prototype.getSide = function() { 

	return this.side;

}

/**
* AnchoredPopupComponent.getState
*
* @returns the state string
**/
AnchoredPopupComponent.prototype.getState = function() { 
	
	return this.state;

}

/**
* AnchoredPopupComponent.setState
*
* @param s The new state
**/
AnchoredPopupComponent.prototype.setState = function( s ) { 

	this.state = s;

}

/**
* AnchoredPopupComponent.isReady
*
* @returns boolean True if state is "open" or "closed", false otherwise
**/
AnchoredPopupComponent.prototype.isReady = function() { 

	if ( this.getState() == "open" || this.getState() == "closed" ) return true;
	return false;

}

/**
* AnchoredPopupComponent.place
*
* Add the popup component to the current window and to the windows scrolling engine
**/
AnchoredPopupComponent.prototype.place = function() { 

	this.container.style.visibility = 'hidden';
	this.container.style.left = '0px';
	this.container.style.top = '0px';
	document.body.appendChild( this.getDOM() );

	var my_width = parseInt( this.container.offsetWidth );
	var my_height = parseInt( this.container.offsetHeight );
	var win_width = getWindowWidth();
	var win_height = getWindowHeight();

	switch( this.side ) { 
		case "top":
			this.container.style.left = this.offset;
			this.container.style.top = getWindowTop();
			break;
		case "bottom":
			this.container.style.left = this.offset;
			this.container.style.top = parseInt( getWindowTop() ) + parseInt( getWindowHeight() ) - parseInt( this.container.offsetHeight );
			break;
		default:
			break;
	}

	//attach the widget to the fixed layout
	if ( window.fixed_component_manager ) {
		window.fixed_component_manager.addComponent( this );
	}

	this.container.style.visibility = 'visible';

}

/**
* AnchoredPopupComponent.openPopup
*
* Open the popup
**/
AnchoredPopupComponent.prototype.openPopup = function() { 

	//make sure the popup is not already opening or closing

	if ( ! this.isReady() ) return;

	this.state = "opening";

	//swap which button is visible
	this.open_tab.hideWidget();
	this.close_tab.showWidget();

	if ( this.ae ) {
		var open_stepper = new AnimationStepper( this, function( stepper ) {
			var o = stepper.object_to_animate;
			var oDOM = o.getDOM();
			
			var next_anchor_size = 0;

			if ( o.getSide() == "top" || o.getSide() == "bottom" ) { 
				
				next_anchor_size = parseInt( o.accordion.style.height ) + 20;
				if ( next_anchor_size >= parseInt( o.contained_component.getWidgetDOM().offsetHeight ) ) {
					o.anchorOpen();
					return false;
				}

				if ( o.getSide() == "bottom" ) {
					o.container.style.top = parseInt( getWindowTop() ) + parseInt( getWindowHeight() ) - parseInt( o.container.offsetHeight );
				}

				o.accordion.style.height = next_anchor_size;

				return true;

			}
			else { 

			}

		}
		);

		open_stepper.setState( "opening" );

		this.ae.addAnimationStepper( open_stepper );

		return;
	}

	this.anchorOpen();

	this.state = "open";

}

/**
* AnchoredPopupComponent.closePopup
*
* Close the popup
**/
AnchoredPopupComponent.prototype.closePopup = function() { 

	if ( ! this.isReady() ) return;

	this.state = "closing";
	this.accordion.style.height = this.contained_component.getWidgetDOM().offsetHeight;

	//swap which button is visible
	this.close_tab.hideWidget();
	this.open_tab.showWidget();

	if ( this.ae ) {

		var close_stepper = new AnimationStepper( this, function( stepper ) {

			var o = stepper.object_to_animate;
			var oDOM = o.getDOM();
			
			var next_anchor_size = 0;

			if ( o.getSide() == "top" || o.getSide() == "bottom" ) { 
				
				next_anchor_size = parseInt( o.accordion.style.height ) - 20;

				if ( next_anchor_size <= 0 ) {
					o.anchorClosed();
					return false;
				}

				o.accordion.style.height = next_anchor_size;

				if ( o.getSide() == "bottom" ) {
					o.container.style.top = parseInt( getWindowTop() ) + parseInt( getWindowHeight() ) - parseInt( o.container.offsetHeight );
				}
				return true;

			}
			else { 

			}

		}
		);

		close_stepper.setState( "closing" );

		this.ae.addAnimationStepper( close_stepper );

		return;
	}

	this.anchorClosed();

	this.state = "closed";

}

/**
* AnchoredPopupComponent.anchorOpen
*
* Set the popup to open based on what side it is attached to
**/
AnchoredPopupComponent.prototype.anchorOpen = function() { 

	switch( this.getSide() ) { 
		case "top":
			//this.accordion.style.height = parseInt( this.contained_component.getWidgetDOM().offsetHeight );
			this.accordion.style.height = "auto";
			break;
		case "right":	
			this.container.style.left = ( parseInt( getWindowLeft() ) + parseInt( getWindowWidth() ) ) - parseInt( this.container.offsetWidth );
			break;
		case "bottom":
			this.accordion.style.height = parseInt( this.contained_component.getWidgetDOM().offsetHeight );
			this.container.style.top = parseInt( getWindowTop() ) + parseInt( getWindowHeight() ) - parseInt( this.container.offsetHeight );
			break;
		case "left":
			this.container.style.left = parseInt( getWindowLeft() );
			break;
	}

	this.state = "open";
}

/**
* AnchoredPopupComponent.anchorClosed
*
* Set the popup to closed based on what side it is attached to
**/
AnchoredPopupComponent.prototype.anchorClosed = function() { 

	//<== NEED TO FIX THIS
	//For some reason, when I set the height of a div to 0 in IE, it defaults to AUTO
	switch( this.getSide() ) { 
		case "top":
			this.accordion.style.height = "1px";
			break;
		case "right":	
			this.accordion.style.width = "1px";
			break;
		case "bottom":
			this.accordion.style.height = "1px";
			this.container.style.top = parseInt( getWindowTop() ) + parseInt( getWindowHeight() ) - parseInt( this.container.offsetHeight );
			break;
		case "left":
			this.accordion.style.width = "1px";
			break;
	}

	this.state = "closed";

}				

/**
* AnchoredPopupComponent.getDOM
*
* @returns DOM representation of the Component
**/
AnchoredPopupComponent.prototype.getDOM = function() { 

	return this.container;

}

