
//backwards compatable function...
function showColorPicker(el, callback, allowTransparency, transparencyCaption) {
	//try and get a color...
	var clr = null;
	if(el.style.backgroundColor != null && el.style.backgroundColor != "") {
		clr = el.style.backgroundColor;
	}
	var opts = {};
	if(allowTransparency) {
		opts.allow_transparency = true;
		if(transparencyCaption != null) {
			opts.transparency_caption = transparencyCaption;
		}
	}
	pwColorPicker.selectColor(null, el, clr, callback, opts);
}


var ColorPicker = Class.create({
	CLASSDEF: {
		name: 'ColorPicker'
	},
	
	initialize: function() {
		this.palettes = {};
		this.processes = {};
		this.bodyClickEvent = this.bodyClick.bindAsEventListener(this);
		this.allColors = {};
	},
	
	registerColor: function(color) {
		this.allColors[color.id] = color;
		
	},
	
	initDefaultPalettes: function() {
		var ids = -1;
		var p = new ColorPalette({id:-1, name:"Web Colors"}, []);
		for(var r=255;r>=0;r-=3*16) {
			for(var g=0;g<=255;g+=3*16) {
				for(var b=0;b<=255;b+=3*16) {
					var c = new ColorPaletteColor([ids--,0,0,0,0,r,g,b,""]);
					convertToCMYK(c);
					p.colors.add(c);
				}
			}
		}
		this.palettes[p.id] = p;
		
		p = new ColorPalette({id:-2, name:"Named Colors"}, []);
		var namedColors = new Array('AliceBlue','AntiqueWhite','Aqua','Aquamarine','Azure','Beige','Bisque','Black','BlanchedAlmond','Blue','BlueViolet','Brown',
			'BurlyWood','CadetBlue','Chartreuse','Chocolate','Coral','CornflowerBlue','Cornsilk','Crimson','Cyan','DarkBlue','DarkCyan','DarkGoldenRod','DarkGray',
			'DarkGreen','DarkKhaki','DarkMagenta','DarkOliveGreen','Darkorange','DarkOrchid','DarkRed','DarkSalmon','DarkSeaGreen','DarkSlateBlue','DarkSlateGray',
			'DarkTurquoise','DarkViolet','DeepPink','DeepSkyBlue','DimGray','DodgerBlue','Feldspar','FireBrick','FloralWhite','ForestGreen','Fuchsia','Gainsboro',
			'GhostWhite','Gold','GoldenRod','Gray','Green','GreenYellow','HoneyDew','HotPink','IndianRed','Indigo','Ivory','Khaki','Lavender','LavenderBlush',
			'LawnGreen','LemonChiffon','LightBlue','LightCoral','LightCyan','LightGoldenRodYellow','LightGrey','LightGreen','LightPink','LightSalmon','LightSeaGreen',
			'LightSkyBlue','LightSlateBlue','LightSlateGray','LightSteelBlue','LightYellow','Lime','LimeGreen','Linen','Magenta','Maroon','MediumAquaMarine',
			'MediumBlue','MediumOrchid','MediumPurple','MediumSeaGreen','MediumSlateBlue','MediumSpringGreen','MediumTurquoise','MediumVioletRed','MidnightBlue',
			'MintCream','MistyRose','Moccasin','NavajoWhite','Navy','OldLace','Olive','OliveDrab','Orange','OrangeRed','Orchid','PaleGoldenRod','PaleGreen',
			'PaleTurquoise','PaleVioletRed','PapayaWhip','PeachPuff','Peru','Pink','Plum','PowderBlue','Purple','Red','RosyBrown','RoyalBlue','SaddleBrown',
			'Salmon','SandyBrown','SeaGreen','SeaShell','Sienna','Silver','SkyBlue','SlateBlue','SlateGray','Snow','SpringGreen','SteelBlue','Tan','Teal','Thistle',
			'Tomato','Turquoise','Violet','VioletRed','Wheat','White','WhiteSmoke','Yellow','YellowGreen');
			
		var namedColorRGB = new Array('#F0F8FF','#FAEBD7','#00FFFF','#7FFFD4','#F0FFFF','#F5F5DC','#FFE4C4','#000000','#FFEBCD','#0000FF','#8A2BE2','#A52A2A','#DEB887',
			'#5F9EA0','#7FFF00','#D2691E','#FF7F50','#6495ED','#FFF8DC','#DC143C','#00FFFF','#00008B','#008B8B','#B8860B','#A9A9A9','#006400','#BDB76B','#8B008B',
			'#556B2F','#FF8C00','#9932CC','#8B0000','#E9967A','#8FBC8F','#483D8B','#2F4F4F','#00CED1','#9400D3','#FF1493','#00BFFF','#696969','#1E90FF','#D19275',
			'#B22222','#FFFAF0','#228B22','#FF00FF','#DCDCDC','#F8F8FF','#FFD700','#DAA520','#808080','#008000','#ADFF2F','#F0FFF0','#FF69B4','#CD5C5C','#4B0082',
			'#FFFFF0','#F0E68C','#E6E6FA','#FFF0F5','#7CFC00','#FFFACD','#ADD8E6','#F08080','#E0FFFF','#FAFAD2','#D3D3D3','#90EE90','#FFB6C1','#FFA07A','#20B2AA',
			'#87CEFA','#8470FF','#778899','#B0C4DE','#FFFFE0','#00FF00','#32CD32','#FAF0E6','#FF00FF','#800000','#66CDAA','#0000CD','#BA55D3','#9370D8','#3CB371',
			'#7B68EE','#00FA9A','#48D1CC','#C71585','#191970','#F5FFFA','#FFE4E1','#FFE4B5','#FFDEAD','#000080','#FDF5E6','#808000','#6B8E23','#FFA500','#FF4500',
			'#DA70D6','#EEE8AA','#98FB98','#AFEEEE','#D87093','#FFEFD5','#FFDAB9','#CD853F','#FFC0CB','#DDA0DD','#B0E0E6','#800080','#FF0000','#BC8F8F','#4169E1',
			'#8B4513','#FA8072','#F4A460','#2E8B57','#FFF5EE','#A0522D','#C0C0C0','#87CEEB','#6A5ACD','#708090','#FFFAFA','#00FF7F','#4682B4','#D2B48C','#008080',
			'#D8BFD8','#FF6347','#40E0D0','#EE82EE','#D02090','#F5DEB3','#FFFFFF','#F5F5F5','#FFFF00','#9ACD32');	
	  for(var i=0; i < namedColors.length; i++) {
			var c = toColorPaletteColor(namedColorRGB[i]);
			c.id = ids--;
			c.name = namedColors[i];
			pwColorPicker.registerColor(c);
			p.colors.add(c);
		}
		this.palettes[p.id] = p;
		this.addProcess(null, [-1, -2], {});
	},
	
	addPalette: function(options, colors) {
		var p = new ColorPalette(options, colors);
		this.palettes[p.id] = p;
	},
	
	addProcess: function(processId, paletteIds, options) {
		this.processes[processId] = {paletteIds:paletteIds, options:options};
	},
	
	//if the process limits colors find the first color in the first palette, otherwise use the fullColorDefault
	getDefaultColor: function(processId, fullColorDefault, defaultColorId) {
		if(defaultColorId != null) {
			var color = this.allColors[defaultColorId];
			if(color != null) {
				return color.getHTMLColor();
			}
		}
		var process = this.processes[processId];
		if(process.options.limitColors != true) {
			log("getDefaultColor: " + processId + " process.options.limitColors != true");
			return fullColorDefault;
		}
		log("getDefaultColor: " + processId + " process.options.limitColors == true, finding first color in first palette");
		for(var i=0; i < process.paletteIds.length; i++) {
			var palette = this.palettes[process.paletteIds[i]];
			for(var j=0; j < palette.colors.list.size(); j++) {
				return palette.colors.list[j].getHTMLColor();
			}
		}
		log("NO COLORS AVAILABLE!");
		return "#000000";
	},
	
	selectColor: function(processId, refElement, currentColor, callback, options) {
		var paletteIds = [];
		if (processId == undefined) processId = null;
		if((this.processes[processId] == null)||(this.processes[processId].paletteIds.length == 0))  {
			if(this.processes[null] == null) {
				this.initDefaultPalettes();
			}
			//processId = null;
			paletteIds = this.processes[null].paletteIds;
		} else {
			paletteIds = this.processes[processId].paletteIds;
		}
		
		log("pwColorPicker.selectColor(" + currentColor + ")");
		log(paletteIds);
		this.callback = callback;
		if(currentColor != null) {
			this.currentColor = toColorPaletteColor(currentColor);
		} else {
			this.currentColor == null;
		}
		log(this.currentColor);
		this.currentPalette = null; //a palette will set this is it contains the currentColor 
		this.refElement = refElement;
		this.options = options;
		var process = this.processes[processId];
		this.loadPalettes(paletteIds, process.options, options);
		
		var pos = Position.cumulativeOffset(refElement);
		var height = $(refElement).getHeight();
		
		this.el.style.top = (pos[1] + height) + "px";
		this.el.style.left = pos[0] + "px";
		
		
	},
	
	loadPalettes: function(paletteIds, options, callOptions) {
		if(this.el == null) {
			
			var html = '<div class="header" id="pwColorPickerHeader" ><a href="#" onclick="pwColorPicker.close(); return false;" class="close">close</a></div><div class="content"><ol class="palette" id="pwColorPaletteTabs"></ol>';
			html += '<div class="interior" id="pwColorPanels">';
			html += '<ul class="slider" style="display: none;" id="pwCP_0_panel">' +
				'<li><label>C</label><span><b id="pwSCC" style="width:210px;"><i id="pwSSC">&nbsp;</i></b><input type="text" value="" id="pwSVC" onkeyup="pwColorPicker.setSliderValue(\'c\', this);" /></span></li>' +
				'<li><label>M</label><span><b id="pwSCM" style="width:210px;"><i id="pwSSM">&nbsp;</i></b><input type="text"  value="" id="pwSVM" onkeyup="pwColorPicker.setSliderValue(\'m\', this);" /></span></li>' +
				'<li><label>Y</label><span><b id="pwSCY" style="width:210px;"><i id="pwSSY">&nbsp;</i></b><input type="text"  value="" id="pwSVY" onkeyup="pwColorPicker.setSliderValue(\'y\', this);" /></span></li>' +
				'<li><label>K</label><span><b id="pwSCK" style="width:210px;"><i id="pwSSK">&nbsp;</i></b><input type="text"  value="" id="pwSVK" onkeyup="pwColorPicker.setSliderValue(\'k\', this);" /></span></li>' +
				'<li class="color" id="pwColorBar_0" style="background-color: #ff0000;" onclick="pwColorPicker.chooseCurrentColor();"><span><b>select</b></span></li>' +
			'</ul>';
		
			html += '<ul class="slider" style="display: none;" id="pwCP_00_panel">' +
				'<li><label>R</label><span><b id="pwSCR" style="width:210px;"><i id="pwSSR">&nbsp;</i></b><input type="text" value="" id="pwSVR" onkeyup="pwColorPicker.setSliderValue(\'r\', this);" /></span></li>' +
				'<li><label>G</label><span><b id="pwSCG" style="width:210px;"><i id="pwSSG">&nbsp;</i></b><input type="text"  value="" id="pwSVG" onkeyup="pwColorPicker.setSliderValue(\'g\', this);" /></span></li>' +
				'<li><label>B</label><span><b id="pwSCB" style="width:210px;"><i id="pwSSB">&nbsp;</i></b><input type="text"  value="" id="pwSVB" onkeyup="pwColorPicker.setSliderValue(\'b\', this);" /></span></li>' +
				'<li class="color" id="pwColorBar_1" style="background-color: #ff0000;" onclick="pwColorPicker.chooseCurrentColor();"><span><b>select</b></span></li>' +
			'</ul>';
			
			html += '</div></div><div class="footer"><span class="color_name" id="pwCPCN" class="visibility:hidden;"></span><a href="#" class="transparent" onclick="pwColorPicker.selectTransparent(); return false;" id="pwMakeTrans">make transparent</a></div>';

			
			this.el = document.createElement("DIV");
			this.el.className = "color_picker";
			this.el.style.display="none";
		
			this.el.setAttribute("stopdeselect","true");
			this.el.innerHTML = html;
			document.body.appendChild(this.el);
			
			this.transButton = $("pwMakeTrans");
			if (!callOptions.allow_transparency) {
			  this.transButton.style.display = "none";
			} else {
			  this.transButton.style.display = "";
			}
			this.tabContainer = $("pwColorPaletteTabs");
			this.paletteContainer = $("pwColorPanels");
			
			this.el.style.zIndex = 30000;
			this.el.style.display="";
			this.dragger = new Draggable(this.el, {handle: "pwColorPickerHeader", zindex: 30000});
			
			Event.observe(document.body, "mousedown", this.bodyClickEvent);
			
			
			this.loadedPalettes = {
				"pwCP_0_tab": $("pwCP_0_panel"),
				"pwCP_00_tab": $("pwCP_00_panel")
			};
			
			this.colorNameEl = $("pwCPCN");
			
			this.sliderC = new Control.Slider('pwSSC', 'pwSCC', { minimum: 0, maximum: 100, range: $R(0,100), values: $R(0,100), sliderValue:0, alignX:10, increment: 210.0/100.0, onSlide: function(v) {this.slideValue("c", v, true);}.bind(this)});
			//$("pwSVC").value = this.currentColor.c;
			this.sliderC = new Control.Slider('pwSSM', 'pwSCM', { minimum: 0, maximum: 100, range: $R(0,100), values: $R(0,100), sliderValue:0, alignX:10,  increment: 210.0/100.0, onSlide: function(v) {this.slideValue("m", v, true);}.bind(this)});
			//$("pwSVM").value = this.currentColor.m;
			this.sliderC = new Control.Slider('pwSSY', 'pwSCY', { minimum: 0, maximum: 100, range: $R(0,100), values: $R(0,100), sliderValue:0, alignX:10,  increment: 210.0/100.0, onSlide: function(v) {this.slideValue("y", v, true);}.bind(this)});
		//	$("pwSVY").value = this.currentColor.y;
			this.sliderC = new Control.Slider('pwSSK', 'pwSCK', { minimum: 0, maximum: 100, range: $R(0,100), values: $R(0,100), sliderValue:0, alignX:10,  increment: 210.0/100.0, onSlide: function(v) {this.slideValue("k", v, true);}.bind(this)});
			//$("pwSVK").value = this.currentColor.k;
			
			
			
			this.sliderR = new Control.Slider('pwSSR', 'pwSCR', { minimum: 0, maximum: 255, range: $R(0,255), values: $R(0,255), sliderValue:0, alignX:10, increment: 210.0/100.0, onSlide: function(v) {this.slideValue("r", v, false);}.bind(this)});
		//	$("pwSVR").value = this.currentColor.r;
			this.sliderG = new Control.Slider('pwSSG', 'pwSCG', { minimum: 0, maximum: 255, range: $R(0,255), values: $R(0,255), sliderValue:0, alignX:10,  increment: 210.0/100.0, onSlide: function(v) {this.slideValue("g", v, false);}.bind(this)});
		//	$("pwSVG").value = this.currentColor.g;
			this.sliderB = new Control.Slider('pwSSB', 'pwSCB', { minimum: 0, maximum: 255, range: $R(0,255), values: $R(0,255), sliderValue:0, alignX:10,  increment: 210.0/100.0, onSlide: function(v) {this.slideValue("b", v, false);}.bind(this)});
		//	$("pwSVB").value = this.currentColor.b;
			
			this.colorBars = [$("pwColorBar_0"), $("pwColorBar_1")];
				
				
			
		}
		
		this.setupPicker(paletteIds, options, callOptions);
			
	
		if(this.currentColor != null) {
			//try and find the color....
			for(var i=0; i < paletteIds.length; i++) {
				var pId = paletteIds[i];
				var palette = this.palettes[pId];
				if(palette.hasColor(this.currentColor)) {
					this.currentPalette = palette;
					break;
				}
			}
		}
			
		
		
		if(this.currentPalette != null) {
			appTabClick("color_picker", "pwCP_" + this.currentPalette.id + "_tab");
		//} else if((this.currentColor != null)&&(options.limitColors != true)) {
		//	appTabClick("color_picker", "pwCP_0_tab"); //select the color slider
		} else {
			if(paletteIds.length > 0) {
				appTabClick("color_picker", "pwCP_" + paletteIds[0] + "_tab");
			} else {
				appTabClick("color_picker", "pwCP_0_tab");
			}
		}
		
		if(this.currentColor ==null) {
			this.currentColor = new ColorPaletteColor([0,0,0,0,0,0,0,0,""]);
		}
		
		
		//color sliders...
		if(options.limitColors != true) {
			if(options.colorMode=="cmyk") {
				$("pwSVC").value = this.currentColor.c;
				this.setSliderValue("c", $("pwSVC"), true);
				$("pwSVM").value = this.currentColor.m;
				this.setSliderValue("m", $("pwSVM"), true);
				$("pwSVY").value = this.currentColor.y;
				this.setSliderValue("y", $("pwSVY"), true);
				$("pwSVK").value = this.currentColor.k;
				this.setSliderValue("k", $("pwSVK"), true);
			} else {
				$("pwSVR").value = this.currentColor.r;
				this.setSliderValue("r", $("pwSVR"), false);
				$("pwSVG").value = this.currentColor.g;
				this.setSliderValue("g", $("pwSVG"), false);
				$("pwSVB").value = this.currentColor.b;
				this.setSliderValue("b", $("pwSVB"), false);
			}
			//this.colorBar.style.backgroundColor = this.currentColor.getHTMLColor();
		}
		this.el.style.display="";
	},
	
	setupPicker: function(paletteIds, options, callOptions) {
		this.tabContainer.innerHTML = this.buildTabs(options, paletteIds);
		for(var k in this.loadedPalettes) {
			this.loadedPalettes[k].style.display = "none";
			log("Hidden " + k );
		}
		/*
		for(var i=0; i < paletteIds.length; i++) {
			var paletteId = paletteIds[i];
			var palette = this.palettes[paletteId];
			html += palette.buildPanelHtml(this.currentColor);
		}
		*/
		if(options.limitColors != true) {
			if(options.colorMode=="cmyk") {
				registerAppTab("color_picker", "pwCP_0_tab", "pwCP_0_panel");
				this.colorBar = this.colorBars[0];
			} else {
				registerAppTab("color_picker", "pwCP_0_tab", "pwCP_00_panel");
				this.colorBar = this.colorBars[1];
			}
		}
		var self = this;
		for(var i=0; i < paletteIds.length; i++) {
			var pId = paletteIds[i];
			registerAppTab("color_picker", "pwCP_" + paletteIds[i] + "_tab", null, { callback: function(id, cbData) { return self.beforeSelectPalette(id, cbData); }, callbackData: pId});
		}
	},
	
	buildTabs: function(options, paletteIds) {
		var html = '';
		if(options.limitColors != true) {
			html += '<li class="slider" id="pwCP_0_tab"><a href="#" onclick="pwColorPicker.selectPalette(0); return false;">slider</a></li>';
		}
		for(var i=0; i < paletteIds.length; i++) {
			var paletteId = paletteIds[i];
			var palette = this.palettes[paletteId];
			html += '<li id="pwCP_' + paletteId + '_tab"><a href="#" onclick="pwColorPicker.selectPalette(' + paletteId + '); return false;">' + palette.name + '</a></li>';
		}
		return html;
	},
	
	beforeSelectPalette: function(tabId, paletteId) {
		log("beforeSelectPalette(" + tabId + "," + paletteId + ")");
		if(this.loadedPalettes[tabId] == null) {
			var palette= this.palettes[paletteId];
			if(palette.colors.list.size() > 70) {
				new Insertion.Bottom(this.paletteContainer, '<ul class="palette_loading" id="pwCP_' + paletteId + '_panel" style="display:none;"><li>Loading...</li></ul>');
				var self = this;
				window.setTimeout(function() {
						self.loadedPalettes[tabId].replace(self.palettes[paletteId].buildPanelHtml(self.currentColor, true));
						self.loadedPalettes[tabId] = $('pwCP_' + paletteId + '_panel');
				}, 100);
			} else {
				new Insertion.Bottom(this.paletteContainer, this.palettes[paletteId].buildPanelHtml(this.currentColor));
			}
			this.loadedPalettes[tabId] = $('pwCP_' + paletteId + '_panel');
		}
		return 'pwCP_' + paletteId + '_panel';
	},
	/*
	setupPanels: function(options, paletteIds) {
		for(var i=0; i < paletteIds.length; i++) {
			var paletteId = paletteIds[i];
			var palette = this.palettes[paletteId];
			html += palette.buildPanelHtml(this.currentColor);
		}
	},*/
	
	slideValue: function(field, value, isCmyk) {
		log("slideValue:" +field + "=" + value + " isCmyk=" + isCmyk);
		$("pwSV" + field.toUpperCase()).value = value;
		this.currentColor[field] = value;
		if(isCmyk) {
			convertToRGB(this.currentColor);
		}
		this.colorBar.style.backgroundColor = this.currentColor.getHTMLColor();
		log(this.colorBar.style.backgroundColor + " " +  this.currentColor.getHTMLColor());
	},
	
	setSliderValue: function(field, el, isCmyk) {
		log("setSliderValue:" +field + "=" + el.value + " isCmyk=" + isCmyk);
		if(!isNaN(el.value)) {
			var val = parseInt(el.value);
			if((val >=0) && (!isCmyk || val <=100) && (isCmyk || val <=255)) {
				this["slider" + field.toUpperCase()].setValue(val);
				this.currentColor[field] = parseInt(el.value, 10);
				if(isCmyk) {
					convertToRGB(this.currentColor);
				}
				this.colorBar.style.backgroundColor = this.currentColor.getHTMLColor();
				
			}
		}
	},
	
	selectPalette: function(paletteId) {
		
	},
	
	chooseColor: function(paletteId, colorId) {
		var color = this.palettes[paletteId].colors.byId[colorId];
		this.callback(color.getHTMLColor(), color);
		this.deleteElements();
	},
	
	chooseCurrentColor: function() {
		this.callback(this.currentColor.getHTMLColor(), this.currentColor);
		this.deleteElements();
	},
	
	selectTransparent: function() {
		this.callback("Transparent", null);
		this.deleteElements();
	},
	
	close: function() {
		this.deleteElements();
	},
	
	//close the picker....
	bodyClick: function(event) {
		var el = Event.element(event);
		while(el != null) {
			if(el == this.el) {
				return;
			}
			el = el.parentNode;
		}
		//if we get here we did not click in the color picker...
		this.deleteElements();
	},
	
	deleteElements: function() {
		log("deleteElements");
		//Event.stopObserving(document.body, "mousedown", this.bodyClickEvent);
		//this.dragger.destroy();
		//document.body.removeChild(this.el);
		//this.el = null;
		this.el.style.display="none";
		clearAppTabs("color_picker");
	},
	
	colorOver: function(id) {
		
		if(id == null) {
			this.colorNameEl.style.visibility = "hidden";
		} else {
			var color = this.allColors[id];
			log(color);
			if(color != null) {
				if(color.name != null && color.name != "") {
					this.colorNameEl.innerHTML =  color.name;
				} else {
					this.colorNameEl.innerHTML = color.getHTMLColor();
				}
				this.colorNameEl.style.visibility = "visible";
			} else {
				this.colorNameEl.style.visibility = "hidden";
			}
		}
	}
});



var ColorPalette = Class.create({
	CLASSDEF: {
		name: 'ColorPalette'
	},
	
	initialize: function(options, colors) {
		this.id = options.id;
		this.name = options.name;
		this.colors = new MapList(this);
		for(var i=0; i < colors.length; i++) {
			this.colors.add(new ColorPaletteColor(colors[i]));
		}
	},
	
	buildPanelHtml: function(currentColor, visible) {
		var style = visible==true ? "" : ' style="display:none;"';
		var html = '<ul class="listing" id="pwCP_' + this.id + '_panel"' + style + '>';
		for(var i=0; i < this.colors.list.size(); i++) {
			var color = this.colors.list[i];
			html += color.buildPanelHtml(currentColor);
			if(color.equals(currentColor)) {
				pwColorPicker.currentPalette = this;
				currentColor.id = color.id;
			}
		}
		html += '</ul>';
		return html;
	},
	
	hasColor: function(color) {
		for(var i=0;i < this.colors.list.size(); i++) {
			if(this.colors.list[i].equals(color)) {
				return true;
			}
		}
		return false;
	}
});

var ColorPaletteColor = Class.create({
	CLASSDEF: {
		name: 'ColorPaletteColor'
	},
	
	initialize: function(options) {
		this.id = options[0]
		this.c = options[1];
		this.m = options[2];
		this.y = options[3];
		this.k = options[4];
		this.r = options[5];
		this.g = options[6];
		this.b = options[7];
		this.name = options[8];
		if(this.id != null) pwColorPicker.registerColor(this);
	},
	
	buildPanelHtml: function() {
		return '<li style="background-color: ' + this.getHTMLColor() + ';" onclick="pwColorPicker.chooseColor(' + this.parentObject.id + ',' + this.id + ');" onmouseover="pwColorPicker.colorOver(' + this.id + ');" onmouseout="pwColorPicker.colorOver(null);" >&nbsp;</li>';
	},
	
	getHTMLColor: function() {
		return "#" + toHex(this.r) + toHex(this.g) + toHex(this.b);
	},
	equals: function(other) {
		if(other == null) return false;
		if((this.c == other.c) && (this.m == other.m) && (this.y == other.y) && (this.k == other.k)) { //do test in CMYK colorspace
			return true;
		}
		return false;
	}
});


function toHex(c) {
	var s = c.toString(16).toUpperCase();
	if(s.length == 1)
		return "0" + s;
	return s;
}

function isHtmlColorString(val, checkHash) {
	if(val == null) return false;
	if(checkHash) { //has is mandatory..
		if(val.substring(0,1) != "#") {
			log("isHtmlColorString:false (color does not start with #)");
			return false;
		}
		val = val.substring(1, val.length); //remove the #
	} else { //hash is optional
		if(val.substring(0,1) == "#") {
			//log("isHtmlColorString: stripping leading #");
			val = val.substring(1, val.length); //remove the #
		}
	}
	if((val != null)&&(val.length == 6)) {
		for(var i=0; i < 6; i++) {
			var cc = val.charCodeAt(i);
			if(!( ((cc >=48)&&(cc <=57)) || ((cc>=65)&&(cc<=70)) || ((cc>=97)&&(cc<=102)) )) {
				log("isHtmlColorString:false (char code " + cc + " at " + i + " invalid)");
				return false;
			}
		}
		return true;
	} else {
		log("isHtmlColorString:false (length (" + val.length + ") != 6)");
		return false;
	}
}

function isCMYKColorString(val) { //internal format of CMYK colors.. starts with a ^, colors are in HEX, 00 padded, ranging from 0-100
	if(val == null) return false;
	if(val.substring(0,1) != "^") {
		return false;
	}
	if(val.length == 9) {
		for(var i=1; i < 9; i++) {
			var cc = val.charCodeAt(i);
			if(!( ((cc >=48)&&(cc <=57)) || ((cc>=65)&&(cc<=70)) || ((cc>=97)&&(cc<=102)) )) {
				return false;
			}
		}
		return true;
	} else {
		return false;
	}
}

//convert a string to a ColorPaletteColor object..
function toColorPaletteColor(strVal) {
	var opts = [null,0,0,0,0,0,0,0,""];
	if(isHtmlColorString(strVal, false)) {
		//log("isHtmlColorString (" + strVal + ")");
		var idx = 0;
		if(strVal.substr(0,1) == "#") {
			idx = 1;
		}
		opts[5] = parseInt(strVal.substr(idx,2), 16);
		opts[6] = parseInt(strVal.substr(idx+2,2), 16);
		opts[7] = parseInt(strVal.substr(idx+4,2), 16);
		
		var cpc = new ColorPaletteColor(opts);
		convertToCMYK(cpc);
		return cpc;
	} else if(isCMYKColorString(strVal)) {
		opts[1] = parseInt(strVal.substr(1, 2), 16);
		opts[2] = parseInt(strVal.substr(3,2), 16);
		opts[3] = parseInt(strVal.substr(5,2), 16);
		opts[4] = parseInt(strVal.substr(7,2), 16);
		
		var cpc = new ColorPaletteColor(opts);
		convertToRGB(cpc);
		return cpc;
	}
	return null;
}



/*
	http://www.neuro.sfc.keio.ac.jp/~aly/polygon/info/color-space-faq.html
*/

function convertToCMYK(entry) {
	
	
	//normalise to 0 - 1
	var r = parseFloat(entry.r) / 255.0;
	var g = parseFloat(entry.g) / 255.0;
	var b = parseFloat(entry.b) / 255.0;
	
	
	var k = minf(minf(1-r,1-g) ,1-b);
	var c = k==1 ? 0 : (1-r-k)/(1-k);
	var m = k==1 ? 0 : (1-g-k)/(1-k);
	var y = k==1 ? 0 : (1-b-k)/(1-k);
	
	
	entry.c = parseInt(c * 100.0);
	entry.m = parseInt(m * 100.0);
	entry.y = parseInt(y * 100.0);
	entry.k = parseInt(k * 100.0);
}

function convertToRGB(entry) {
	//normalise to 0 - 1
	var c = parseFloat(entry.c) / 100.0;
	var m = parseFloat(entry.m) / 100.0;
	var y = parseFloat(entry.y) / 100.0;
	var k = parseFloat(entry.k) / 100.0;

	var r = 1.0 - minf( 1.0, c*(1-k)+k);
	var g = 1.0 - minf( 1.0, m*(1-k)+k);
	var b = 1.0 - minf( 1.0, y*(1-k)+k);

	entry.r = parseInt(r * 255.0);
	entry.g = parseInt(g * 255.0);
	entry.b = parseInt(b * 255.0);
}

function minf(l,r) {
	if(l < r)
		return l;
	return r;
}

var pwColorPicker = new ColorPicker();
