/**
 *	A small single instance object with some useful methods for interacting with
 *	the ColorScheme class.
*/
colorapp.ColorSchemeHelpers = new function() {
	/**
	 *	Checks for a valid parent element that has a class of 'box'
	 *	@param HTMLElement ele		The element whose parent you want to retrieve.
	 *	@return HTMLElement			The parent element.
	*/
	this.getValidParent = function(ele) {
		if ( xHasClass( ele, 'box' ) || ele.tagName == 'BODY' ) {
			return ele;
		}
		else {
			return colorapp.ColorSchemeHelpers.getValidParent( xParent(ele,true) );
		}
	};


	/**
	 *	The onclick event attached to each element in <code>colorapp.ColorScheme.c</code>.
	 *	@param Event e				event object
	*/
	this.setMyColor = function(e) {
		var evt = new xEvent(e);
		// specifically disclude the child INPUT element so people can actually mark 
		// text within the INPUT element (rather than the annoyance of having 
		// everything marked).
		if ( evt.target.tagName != 'INPUT' ) {
			var ele = colorapp.ColorSchemeHelpers.getValidParent(evt.target);
			var eDiv   = xFirstChild( ele, 'div' );
			var eInput = xFirstChild( ele, 'input' );
			eDiv.style.display = 'none';
			eInput.style.display = 'inline';
			eInput.focus();
			eInput.select();
		}
	};

	/**
	 *	A method attached to onBlur event of the text input child of each element in 
	 *	colorapp.ColorScheme.c that will hide the text input box when the cursor 
	 *	leaves it's focus.
	 *	@param Event e				event object
	*/
	this.setOnBlur = function(e) {
		var evt = new xEvent(e);
		var ele = colorapp.ColorSchemeHelpers.getValidParent(evt.target);
		var eDiv   = xFirstChild( ele, 'div' );
		var eInput = xFirstChild( ele, 'input' );
		eDiv.style.display = 'block';
		eInput.style.display = 'none';
		ele.changeBoxColor(eInput.value);
	};

	/**
	 *	A method attached to onChange event of the text input child of each element in 
	 *	colorapp.ColorScheme.c that will execute the element's <code>changeBoxColor()</code> 
	 *	giving it the value in the text input box.
	 *	@param Event e				event object
	*/
	this.setOnChange = function(e) {
		// IE doesn't provide an event object, but it does provide window.event - xEvent creates
		// a compatible event object for multiple browsers.
		var evt = new xEvent(e);
		var ele = colorapp.ColorSchemeHelpers.getValidParent(evt.target);
		var eInput = xFirstChild( ele, 'input' );
		ele.changeBoxColor(eInput.value);
	};

	/**
	 *	A method attached to each element in colorapp.ColorScheme.c that will execute 
	 *	a colorapp.ColorScheme method based upon a preset property.
	 *
	 *	this.myColorSchemeSelector should be 1 of the ColorScheme setters mentioned in 
	 *	colorapp.ColorScheme.prototype._setBoxColor method definition.
	 *
	 *	@param string hexColor					A valid #nnn or #nnnnnn hex formatted color
	*/
	this.changeBoxColor = function(hexColor) {
		if ( this.myColorSchemeSelector ) {
			var cColor = new colorapp.Color(hexColor);
			colorapp.colorScheme[ this.myColorSchemeSelector ]( cColor );
		}
	};


	/**
	 *	Sets the HTMLElement <var>eleOrId</var>'s background-color to the color given by <var>hexColor</var>.
	 *	@param string/HTMLElement eleOrId		The HTMLElement to be affected
	 *	@param string hexColor					A valid #nnn or #nnnnnn hex formatted color
	*/
	this.setBGColor = function( eleOrId, hexColor ) {
		var bg = xGetElementById( eleOrId );
		bg.style.backgroundColor = hexColor;
	}
	/**
	 *	Sets the HTMLElement <var>eleOrId</var>'s text color to the color given by <var>hexColor</var>.
	 *	@param string/HTMLElement eleOrId		The HTMLElement to be affected
	 *	@param string hexColor					A valid #nnn or #nnnnnn hex formatted color
	*/
	this.setColor = function( eleOrId, hexColor ) {
		var bg = xGetElementById( eleOrId );
		bg.style.color = hexColor;
	}
};


/* **** start define ColorScheme **** */
colorapp.ColorScheme = function() {
	// needs to be a per instantiated object collection as the actual HTMLElement
	// objects will be assigned back into this hashmap.
	// i.e. this.c['page_text'] = document.getElementById( 'setPageText' );
	this.c = {
		'page_text':			'setPageText',
		'page_bg':				'setPageBackground',
		'page_link':			'setPageLink',
		'page_link_hover':		'setPageLinkHover',
		'striping':				'setStripe',
		'header_text':			'setHeaderText',
		'nav_border':			'setNavBorder',
		'nav_link':				'setNavLink',
		'nav_link_bg':			'setNavLinkBackground',
		'nav_link_hover':		'setNavLinkHover',
		'nav_link_hover_bg':	'setNavLinkHoverBackground'
	};

	// initialize the object.
	this.init();
};

	// constant values - do not modify !!
	colorapp.ColorScheme.prototype.FOREGROUND = 0;
	colorapp.ColorScheme.prototype.BACKGROUND = 1;

	/**
	 *	The object constructor method.  This is forced to run on a per object instantiation
	 *	basis by the this.init(); within the Class definition.
	 *	
	 *	For each item in "this.c"
	 *		* The corresponding HTMLElement retrieved via ID is attached to "this.c".
	 *		* An onclick event is attached to the HTMLElement.
	 *		* The child text input is retrieved and has 2 events attached to it.
	 *			* onblur   is set to colorapp.ColorSchemeHelpers.setOnBlur
	 *			* onchange is set to colorapp.ColorSchemeHelpers.setOnChange
	 *		* A changeBoxColor() method is attached to the HTMLElement 
	 *			(see colorapp.ColorSchemeHelpers.changeBoxColor).
	 *		* A myColorSchemeSelector property is set which corresponds to the 
	 *			ColorScheme class method to be executed by the changeBoxColor() 
	 *			that was previously attached.
	 *	
	 *	@return void
	*/
	colorapp.ColorScheme.prototype.init = function() {
		for ( var i in this.c ) {
			if ( this.c.hasOwnProperty(i) ) {
				var tmp = this.c[i];
				this.c[i] = xGetElementById( i );
				xAddEventListener( this.c[i], 'click', colorapp.ColorSchemeHelpers.setMyColor );
				var eInput = xFirstChild( this.c[i], 'input' );
				xAddEventListener( eInput, 'blur', colorapp.ColorSchemeHelpers.setOnBlur );
				xAddEventListener( eInput, 'change', colorapp.ColorSchemeHelpers.setOnChange );
				this.c[i].changeBoxColor = colorapp.ColorSchemeHelpers.changeBoxColor;
				this.c[i].myColorSchemeSelector = tmp;
			}
		}
	}

	/**
	 *	*Private Method*  This sets the background & foreground color for each 
	 *	color box as well as populating it's contents with the hex value of the 
	 *	contained color.
	 *
	 *	This is to prevent duplication within several other setter methods.  You 
	 *	should use the specific setter method instead of this generic method as 
	 *	they set specific other things as well -
	 *		* setPageText
	 *		* setPageBackground
	 *		* setPageLink
	 *		* setPageLinkHover
	 *		* setStripe
	 *		* setHeaderText
	 *		* setNavBorder
	 *		* setNavLink
	 *		* setNavLinkBackground
	 *		* setNavLinkHover
	 *		* setNavLinkHoverBackground
	 *
	 *	@param string id		The ID from this.c for the element to be modified
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype._setBoxColor = function(id,color,isBGColor) {
		if( color instanceof colorapp.Color ) {
			if ( this.c[id] ) {
				var loc;
				var hexColor = color.toHexColor();
				this.c[id].style.backgroundColor = hexColor;
				this.c[id].style.color = color.getContrastColor();
				var txtbox = xFirstChild( this.c[id], 'div' );
				txtbox.innerHTML = hexColor;
				var txtbox = xFirstChild( this.c[id], 'input' );
				txtbox.value = hexColor;
			}
			else {
//				throw new colorapp.ColorAppException( 'Invalid ColorScheme ID' );
			}
		}
		else {
//			throw new colorapp.ColorAppException('color argument sent to setBoxColor is not of type colorapp.Color' );
		}
	};



	/**
	 *	Sets the information and specific HTMLElements for setPageText to the specified color.
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setPageText = function(color,ele) {
		this._setBoxColor('page_text', color );
		ele = ele || xGetElementById( 'display' );
		colorapp.ColorSchemeHelpers.setColor( ele, color.toHexColor() );
	};
	/**
	 *	Sets the information and specific HTMLElements for setPageBackground to the specified color.
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setPageBackground = function(color,ele) {
		this._setBoxColor('page_bg', color, true );
		ele = ele || xGetElementById( 'display' );
		colorapp.ColorSchemeHelpers.setBGColor( ele, color.toHexColor() );
	};
	/**
	 *	Sets the information and specific HTMLElements for setPageLink to the specified color.
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setPageLink = function(color) {
		this._setBoxColor('page_link', color );
		this.setLinkItems( 'display_body', 'outColor', color, colorapp.ColorSchemeHelpers.setColor );
	};
	/**
	 *	Sets the information and specific HTMLElements for setPageLinkHover to the specified color.
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setPageLinkHover = function(color) {
		this._setBoxColor('page_link_hover', color );
		this.setLinkItems( 'display_body', 'overColor', color );
	};
	/**
	 *	Sets the information and specific HTMLElements for setStripe to the specified color.
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setStripe = function(color,ele) {
		this._setBoxColor('striping', color, true );
		ele = xGetElementById( 'display_header' );
		colorapp.ColorSchemeHelpers.setBGColor( ele, color.toHexColor() );
		ele = xGetElementById( 'display_menu' );
		colorapp.ColorSchemeHelpers.setBGColor( ele, color.toHexColor() );
	};
	/**
	 *	Sets the information and specific HTMLElements for setHeaderText to the specified color.
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setHeaderText = function(color,ele) {
		this._setBoxColor('header_text', color );
		ele = ele || xGetElementById( 'display_header' );
		colorapp.ColorSchemeHelpers.setColor( ele, color.toHexColor() );
	};
	/**
	 *	Sets the information and specific HTMLElements for setNavBorder to the specified color.
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setNavBorder = function(color,ele) {
		this._setBoxColor('nav_border', color );
		var disp = xGetElementById( 'display' );
		var eles  = xGetElementsByTagName( 'ul', disp );
		for ( var i=0; i<eles.length; i++ ) {
			eles[i].style.borderColor = color.toHexColor();
		}
	};
	/**
	 *	Sets the information and specific HTMLElements for setNavLink to the specified color.
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setNavLink = function(color) {
		this._setBoxColor('nav_link', color );
		this.setLinkItems( 'display_menu', 'outColor', color, colorapp.ColorSchemeHelpers.setColor );
	};
	/**
	 *	Sets the information and specific HTMLElements for setNavLinkBackground to the specified color.
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setNavLinkBackground = function(color) {
		this._setBoxColor('nav_link_bg', color, true );
		this.setLinkItems( 'display_menu', 'outBackgroundColor', color, colorapp.ColorSchemeHelpers.setBGColor );
	};
	/**
	 *	Sets the information and specific HTMLElements for setNavLinkHover to the specified color.
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setNavLinkHover = function(color) {
		this._setBoxColor('nav_link_hover', color );
		this.setLinkItems( 'display_menu', 'overColor', color );
	};
	/**
	 *	Sets the information and specific HTMLElements for setNavLinkHoverBackground to the specified color.
	 *	@param Color color		requires a valid colorapp.Color object
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setNavLinkHoverBackground = function(color) {
		this._setBoxColor('nav_link_hover_bg', color, true );
		this.setLinkItems( 'display_menu', 'overBackgroundColor', color );
	};

	/**
	 *	*Private Method*  This loops over all A tags within <var>containerId</var> and sets the 
	 *	property <var>setting</var> to the value <var>color</var><code>.toHexColor()</code>.  It 
	 *	will also execute a helper function <var>func</var> given 2 parameters - the HTMLElement 
	 *	and <var>color</var><code>.toHexColor()</code>.
	 *	@param string/HTMLElement containerId		the HTML element to search for A tags
	 *	@param string setting		the property to be set (outColor, outBackgroundColor, overColor, or overBackgroundColor)
	 *	@param Color color			requires a valid colorapp.Color object
	 *	@param function func		a function taking 2 parameters - an HTMLElement object & a string hex color (#aaaaaa where a is a digit between 0 & f)
	 *	@returns void
	*/
	colorapp.ColorScheme.prototype.setLinkItems = function(containerId,setting,color,func) {
		if( color instanceof colorapp.Color ) {
			var disp = xGetElementById( containerId );
			var eles  = xGetElementsByTagName( 'a', disp );
			for ( var i=0; i<eles.length; i++ ) {
				eles[i][setting] = color.toHexColor();
				
				if ( func ) {
					func(   eles[i], eles[i][setting] );
				}
			}
		}
	};

/* **** end define ColorScheme **** */

