ColorPicker = new Class({
	initialize: function(objParent, InitialColor){
		//if this is a color us it if not try to make a color out of it.
		if(InitialColor.isColor)
			this.CurColor = InitialColor;
		else
			this.CurColor = new Color(InitialColor);
		//If the object was passed as a string get and Element with that ID otherwise use the element.
		if(typeof objParent == 'string')
			this.Parent = $(objParent);
		else
			this.Parent = objParent;

		//These are member variables to hold function pointers to be called with the 
		//buttons in the color dialog.
		this.OKCallback = null;
		this.CancelCallback = null;

		//Create the main container for our color picker.
		this.Container = new Element("div");
		this.Container.setStyle("border", "solid 1px #000000");
		this.Container.setStyle("background-color", "#aaa");
		this.Container.setStyle("width", "460px");
		this.Container.setStyle("padding", "5px");
		this.Parent.appendChild(this.Container);

		//create the container for the hue bar.
		this.HueBar = new Element("div");
		this.HueBar.setStyle("width", "30px");
		this.HueBar.setStyle("cssFloat", "left");
		this.HueBar.setStyle("styleFloat", "left");
		this.HueBar.setStyle("margin-right", "5px");
		this.Container.appendChild(this.HueBar);
		
		//create the container for the Saturation Value Box.
		this.SVBox = new Element("div");
		this.SVBox.setStyle("cssFloat", "left");
		this.SVBox.setStyle("styleFloat", "left");
		this.Container.appendChild(this.SVBox);
		
		//create the container for the Color Swatches and Text Boxes.
		this.ColorInfo = new Element("div");
		this.ColorInfo.setStyle("cssFloat", "left");
		this.ColorInfo.setStyle("styleFloat", "left");
		this.ColorInfo.setStyle("text-align", "center");
		this.ColorInfo.setStyle("margin-left", "3px");
		this.Container.appendChild(this.ColorInfo);

		//Add an empty div to the end to clear the floats.
		this.ClearBreak = new Element("div");
		this.ClearBreak.setStyle("clear", "both");
		this.Container.appendChild(this.ClearBreak);

		//create the color swatches.
		this.SelectedColorLable = new Element("text");
		this.SelectedColorLable.textContent = "Color:";
		this.SelectedColor = new Element("div");
		this.SelectedColor.setStyle("width", "50px");
		this.SelectedColor.setStyle("height", "50px");
		this.SelectedColor.setStyle("margin-left", "auto");
		this.SelectedColor.setStyle("margin-right", "auto");
		this.ColorInfo.appendChild(this.SelectedColorLable);
		this.ColorInfo.appendChild(this.SelectedColor);

		this.PreviewColorLable = new Element("text");
		this.PreviewColorLable.textContent = "Preview:";
		this.PreviewColor = new Element("div");
		this.PreviewColor.setStyle("width", "50px");
		this.PreviewColor.setStyle("height", "50px");
		this.PreviewColor.setStyle("margin-left", "auto");
		this.PreviewColor.setStyle("margin-right", "auto");
		this.ColorInfo.appendChild(this.PreviewColorLable);
		this.ColorInfo.appendChild(this.PreviewColor);

		//Create the container for the hsv and rgb text boxes
		this.ColorInputsContainer = new Element("div");
		this.ColorInputsContainer.setStyle("width", "100%");
		this.ColorInputsContainer.setStyle("text-align", "left");
		this.ColorInputsContainer.setStyle("font-family", "Arial, Helvetica, sans-serif");
		this.ColorInputsContainer.setStyle("margin-left", "5px");
		this.ColorInfo.appendChild(this.ColorInputsContainer);

		//Create the hsv and rgb text fields.
		this.hLabel = new Element("text");
		this.hLabel.textContent = "H:";
		this.hInput = new Element("input");
		this.hInput.size = "3";
		this.hInput.name = "h";
		this.hInput.type = "text";
		this.hInput.addEvent('keyup', this.setHSL.bind(this));
		this.ColorInputsContainer.appendChild(new Element("br"));
		this.ColorInputsContainer.appendChild(this.hLabel);
		this.ColorInputsContainer.appendChild(this.hInput);
		this.ColorInputsContainer.appendChild(new Element("br"));

		this.sLabel = new Element("text");
		this.sLabel.textContent = "S:";
		this.sInput = new Element("input");
		this.sInput.size = "3";
		this.sInput.name = "s";
		this.sInput.type = "text";
		this.sInput.addEvent('keyup', this.setHSL.bind(this));
		this.ColorInputsContainer.appendChild(this.sLabel);
		this.ColorInputsContainer.appendChild(this.sInput);
		this.ColorInputsContainer.appendChild(new Element("br"));

		this.vLabel = new Element("text");
		this.vLabel.textContent = "V:";
		this.vInput = new Element("input");
		this.vInput.size = "3";
		this.vInput.name = "v";
		this.vInput.type = "text";
		this.vInput.addEvent('keyup', this.setHSL.bind(this));
		this.ColorInputsContainer.appendChild(this.vLabel);
		this.ColorInputsContainer.appendChild(this.vInput);
		this.ColorInputsContainer.appendChild(new Element("br"));

		this.rLabel = new Element("text");
		this.rLabel.textContent = "R:";
		this.rInput = new Element("input");
		this.rInput.size = "3";
		this.rInput.name = "r";
		this.rInput.type = "text";
		this.rInput.addEvent('keyup', this.setRGB.bind(this));
		this.ColorInputsContainer.appendChild(new Element("br"));
		this.ColorInputsContainer.appendChild(this.rLabel);
		this.ColorInputsContainer.appendChild(this.rInput);
		this.ColorInputsContainer.appendChild(new Element("br"));

		this.gLabel = new Element("text");
		this.gLabel.textContent = "G:";
		this.gInput = new Element("input");
		this.gInput.size = "3";
		this.gInput.name = "g";
		this.gInput.type = "text";
		this.gInput.addEvent('keyup', this.setRGB.bind(this));
		this.ColorInputsContainer.appendChild(this.gLabel);
		this.ColorInputsContainer.appendChild(this.gInput);
		this.ColorInputsContainer.appendChild(new Element("br"));

		this.bLabel = new Element("text");
		this.bLabel.textContent = "B:";
		this.bInput = new Element("input");
		this.bInput.size = "3";
		this.bInput.name = "b";
		this.bInput.type = "text";
		this.bInput.addEvent('keyup', this.setRGB.bind(this));
		this.ColorInputsContainer.appendChild(this.bLabel);
		this.ColorInputsContainer.appendChild(this.bInput);
		this.ColorInputsContainer.appendChild(new Element("br"));

		//create the ok button and set its onclick callback
		this.okInput = new Element("input");
		this.okInput.name = "OK";
		this.okInput.value = "OK";
		this.okInput.type = "button";
		this.okInput.addEvent('click', this.handleOK.bind(this));
		this.ColorInputsContainer.appendChild(this.okInput);
		this.ColorInputsContainer.appendChild(new Element("br"));
		
		//create the ok button and set its onclick callback
		this.cancelInput = new Element("input");
		this.cancelInput.name = "Cancel";
		this.cancelInput.value = "Cancel";
		this.cancelInput.type = "button";
		this.cancelInput.addEvent('click', this.handleCancel.bind(this));
		this.ColorInputsContainer.appendChild(this.cancelInput);
		this.ColorInputsContainer.appendChild(new Element("br"));

		//Draw the Hue Bar
		this.drawHueBar();
		//Draw the SVBox
		this.drawSVBox();
	},
	//Iterates through all 360 hues and creates a 1px by 30px div for each hue.
	drawHueBar: function (){
		//Create a new color with hue at 0 and S and V at 100%
		hsvColor = new Color([0,100,100], 'hsb');
		//Create the one Hue element and set it's styles.
		fcoDiv = new Element("div");
		fcoDiv.setStyle("width","30px");
		fcoDiv.setStyle("height","1px");
		//Loop through the hues
		for(ci = 0; ci < 360; ci++){
			//User the changeHue to change the existing color object's hue.
			hsvColor.changeHue(ci);
			//Clone the Hue element and inject it inside the Hue Bar.
			coDiv = fcoDiv.clone().injectInside(this.HueBar);
			//Set the huse of the new Hue Element
			coDiv.setStyle("background-color", hsvColor);
			//Set the onClick callback function for the new Hue element.
			coDiv.addEvent('click', this.setCurrentHue.bind(this));
		}
	},
	//Draw a SV box that is as tall as the HUE Bar.
	drawSVBox: function(objsvDiv){
		//Specify the size of the SV Box svSize is used for both width and height.
		svSize = 35;
		//Set the size of the "pixels" for the SVBox.
		pixelSize = 10;
		//Get the multiple required to go from 0 to 100 is svSize steps.
		svStep = 100/svSize;
		
		//Create the color we will use to set the color of the SV Pixels
		svColor =  new Color([this.CurColor[0],this.CurColor[1],this.CurColor[2]]);
		
		//Create a div that will hold 1 row of pixels.
		// this is done to prevent to reduce the number of 
		// appends into the document.
		rcDiv = new Element("div");
		rcDiv.style.clear = "left";
		rcDiv.style.width = (svSize*pixelSize)+"px";
		rcDiv.style.height = pixelSize+"px";
		
		//Create the one pixel that we will clone for each pixel.
		fcoDiv = new Element("div");
		fcoDiv.setStyle("width", pixelSize + "px");
		fcoDiv.setStyle("height", pixelSize + "px");
		fcoDiv.setStyle("cssFloat", "left");
		fcoDiv.setStyle("styleFloat", "left");

		//Iterate over each step in the row injecting cloaned divs into it.
		for(ei = 0; ei < svSize; ei++){
			fcoDiv.clone().injectInside(rcDiv);
		}

		//Iterate over the height of the SV box setting each rows colors.
		for(vi = svSize; vi >= 0; vi -= 1){
			//set the brightness for this row.
			svColor.changeBrightness(vi*svStep);
			//Cloan the row into the SVBox container.
			trcDiv = rcDiv.clone().injectInside(this.SVBox);
			//Get the children of this row.
			arChildren = trcDiv.getChildren();
			//Iterate the children of this row.
			for(ci = 0; ci < arChildren.length; ci++){
				//Change the saturation for each pixe.
				svColor.changeSaturation(ci*svStep);
				arChildren[ci].setStyle("background-color", svColor);
				//Set the events for each pixels for color choice and preview.
				arChildren[ci].addEvent('click', this.setSelectedColor.bind(this));
				arChildren[ci].addEvent('mouseover', this.setPreviewColor.bind(this));
			}
		}
	},
	//Update the pixels in the SVBox when the hue is clicked.
	UpdateSVBox: function (){
		//Get the child rows in the SVBox
		arSVRows = this.SVBox.getChildren();
		//set the svSize to the number of rows.
		svSize = arSVRows.length;
		//Get the multiple required to go from 0 to 100 is svSize steps.
		svStep = 100/svSize;
		//Create a color for calculating the HSV of each pixel.
		svColor =  new Color([this.CurColor[0],this.CurColor[1],this.CurColor[2]]);
		
		//Loop over all of the rows.
		for(vi = svSize - 1; vi >= 0; vi -= 1){
			//set the brightness for this row.
			svColor.changeBrightness(vi*svStep);
			//Get the children of the row.
			siChildren = arSVRows[svSize - vi - 1].getChildren();
			//Iterate the children of this row.
			for(si = 0; si < siChildren.length; si++){
				//Change the saturation for each pixe.
				svColor.changeSaturation(si*svStep);
				siChildren[si].setStyle("background-color", svColor);		
			}	
		}

	},
	setCurrentHue: function (e){
		//IE uses srcElement instead of target to specify the 
		//element that was clicked.
		if(!e.target)
			e.target = e.srcElement;
		//Create a color object from the background of the target so we can
		//get its Hue.
		CurHueColor = new Color(e.target.getStyle("background-color"));
		//Set the Hue of the current color.
		this.CurColor.changeHue(CurHueColor.hsb[0]);
		//Tell the SVBox to update.
		this.UpdateSVBox();
		//Set the selected color to the current color.
		this.SelectedColor.setStyle("background-color", this.CurColor);
		//Update the hsv and rgb text boxes.
		this.hInput.value = this.CurColor.hsb[0];
		this.sInput.value = this.CurColor.hsb[1];
		this.vInput.value = this.CurColor.hsb[2];
		this.rInput.value = this.CurColor[0];
		this.gInput.value = this.CurColor[1];
		this.bInput.value = this.CurColor[2];	
	},
	setPreviewColor: function (e){
		//IE uses srcElement instead of target to specify the 
		//element that was clicked.
		if(!e.target)
			e.target = e.srcElement;
		nColor = new Color(e.target.getStyle("background-color"));
		this.PreviewColor.setStyle("background-color", nColor);
	},

	setSelectedColor: function (e){
		//IE uses srcElement instead of target to specify the 
		//element that was clicked.
		if(!e.target)
			e.target = e.srcElement;
		nColor = new Color(e.target.getStyle("background-color"));
		this.CurColor = nColor;
		this.SelectedColor.setStyle("background-color", nColor);
		this.hInput.value = nColor.hsb[0];
		this.sInput.value = nColor.hsb[1];
		this.vInput.value = nColor.hsb[2];
		this.rInput.value = nColor[0];
		this.gInput.value = nColor[1];
		this.bInput.value = nColor[2];	

	},
	setRGB: function (){
		nc = new Color([this.rInput.value, this.gInput.value, this.bInput.value]);
		this.CurColor = nc;
		this.hInput.value = nc.hsb[0];
		this.sInput.value = nc.hsb[1];
		this.vInput.value = nc.hsb[2];
		this.SelectedColor.setStyle("background-color", nc);
		this.PreviewColor.setStyle("background-color", nc);
		this.UpdateSVBox();
	},
	setHSL: function (){
		nc = new Color([this.hInput.value, this.sInput.value, this.vInput.value], 'hsb');
		this.CurColor = nc;
		this.rInput.value = nc[0];
		this.gInput.value = nc[1];
		this.bInput.value = nc[2];	
		this.SelectedColor.setStyle("background-color", nc);
		this.PreviewColor.setStyle("background-color", nc);
		this.UpdateSVBox();
	},
	//When the ok button is clicked call this.OKCallBack();
	handleOK: function (){
		if(this.OKCallback != null)
			this.OKCallback();
	},
	//When the ok button is clicked call this.CancelCallback();
	handleCancel: function (){
		if(this.CancelCallback != null)
			this.CancelCallback();
	}

});