/**
 * HSVColorPicker
 * 
 * @author Kazuyuki Nishijima
 */

var HSVColorPicker = Class.create();
HSVColorPicker.prototype = {

	version: "00.02.00",

	element: null,

	dialog: null,
	
	svCell: null,
	
	hue: null,
	
	svCellArray: Array(),
	
	appended: false,
	
	initialize: function(options) {
		options = (options == null) ? Array() : options;
		options["unit"] = (options["unit"] == null) ? "em" : options["unit"];
		options["width"] = (options["width"] == null) ? 1 : options["width"];
		options["hStep"] = (options["hStep"] == null) ? 15 : options["hStep"];
		options["sStep"] = (options["sStep"] == null) ? 0.2 : options["sStep"];
		options["vStep"] = (options["vStep"] == null) ? 0.2 : options["vStep"];
		options["zIndex"] = (options["zIndex"] == null) ? 1 : options["vStep"];
		options["delay"] = (options["delay"] == null) ? 100 : options["delay"];
		options["hueClick"] = (options["hueClick"] == null) ? false : options["hueClick"];
		options["closeButton"] = (options["closeButton"] == null) ? true : options["closeButton"];
		this.options = options;
		
		this._initializeDialog();
	},
	
	show: function(id, left, top) {
		if (this.appended == false) {
			document.body.appendChild(this.dialog);
			this.appended = true;
		}
		
		this.element = $(id);
		
		if (left == null) {
			this.dialog.style.left = this.element.offsetLeft + "px";
		} else {
			this.dialog.style.left = left + this.options["unit"];
		}
		
		if (top == null) {
			this.dialog.style.top = (this.element.offsetTop + this.element.offsetHeight) + "px";
		} else {
			this.dialog.style.top = top + this.options["unit"];
		}
		
		setTimeout(this._show.bind(this), this.options["delay"]);
	},
	
	hide: function() {
		setTimeout(this._hide.bind(this), this.options["delay"]);
	},
	
	selectColor: function(r, g, b) {
		var rgbString = ColorUtil.rgbToString(r, g, b);
		this.element.value = rgbString;
		if (this.element.onchange) {
			this.element.onchange();
		}
	},
	
	selectHue: function(hue) {
		if (this.hue == hue) {
			return;
		}
		
		var tmpDisplay = this.dialog.style.display;
		this.dialog.style.display = "none";
		var cellCount = this.svCellArray.length;
		for (var i = 0; i < cellCount; i++) {
			var cell = this.svCellArray[i];
			cell.changeHue(hue);
		}
		this.dialog.style.display = tmpDisplay;
		
		this.hue = hue;
	},
	
	_show: function() {
		this.dialog.style.display = "block";
	},
	
	_hide: function() {
		this.dialog.style.display = "none";
	},
	
	_initializeDialog: function() {
		var hMaxCount = 360 / this.options["hStep"];
		var sMaxCount = 1 / this.options["sStep"] + 1;
		var vMaxCount = 1 / this.options["vStep"] + 1;
		
		this.dialogWidth = (Math.sqrt(Math.pow(sMaxCount, 2) + Math.pow(vMaxCount, 2)) + 2) * this.options["width"];
		
		this.dialog = document.createElement("div");
		this.dialog.style.display = "none";
		this.dialog.style.position = "absolute";
		this.dialog.style.width = (this.dialogWidth + 1) + this.options["unit"];
		this.dialog.style.height = (this.dialogWidth + 1) + this.options["unit"];
		this.dialog.style.left = "0px";
		this.dialog.style.top = "0px";
		this.dialog.style.zIndex = this.options["zIndex"];
		Element.addClassName(this.dialog, "HSVColorPicker_dialog");
		
		this._initializeSVSelecter(sMaxCount, vMaxCount);
		this._initializeHSelecter(hMaxCount);
		
		if (this.options["closeButton"] == true) {
			var button = this._initializeCloseButton();
			this.dialog.appendChild(button);
		}
		
		this.dialog.appendChild(this.hSelecter);
		this.dialog.appendChild(this.svSelecter);
	},
	
	_initializeSVSelecter: function(sMaxCount, vMaxCount) {
		this.svSelecter = document.createElement("div");
		this.svSelecter.style.position = "absolute";
		this.svSelecter.style.width = (sMaxCount * this.options["width"]) + this.options["unit"];
		this.svSelecter.style.height = (vMaxCount * this.options["width"]) + this.options["unit"];
		this.svSelecter.style.left = ((this.dialogWidth + this.options["width"]) / 2 - (vMaxCount / 2 * this.options["width"])) + this.options["unit"];
		this.svSelecter.style.top = ((this.dialogWidth + this.options["width"]) / 2 - (sMaxCount / 2 * this.options["width"])) + this.options["unit"];
		Element.addClassName(this.svSelecter, "HSVColorPicker_svSelecter");
		
		var h = 0;
		var widthString = this.options["width"] + this.options["unit"];
		for (var sCount = sMaxCount - 1; sCount >= 0; sCount--) {
			var s = sCount * this.options["sStep"];
			var top = (sCount * this.options["width"]) + this.options["unit"];
			for (var vCount = 0; vCount < vMaxCount; vCount++) {
				var v = vCount * this.options["vStep"];
				var left = (vCount * this.options["width"]) + this.options["unit"];
				
				var svCell = new SVColorCell(this, widthString, widthString, left, top, h, s, v);
				this.svSelecter.appendChild(svCell.element);
				
				this.svCellArray.push(svCell);
			}
		}
	},
	
	_initializeHSelecter: function(hMaxCount) {
		this.hSelecter = document.createElement("div");
		this.hSelecter.style.position = "absolute";
		this.hSelecter.style.width = this.dialog.style.width;
		this.hSelecter.style.height = this.dialog.style.height;
		this.hSelecter.style.left = "0px";
		this.hSelecter.style.top = "0px";
		Element.addClassName(this.hSelecter, "HSVColorPicker_hSelecter");
		
		var widthString = this.options["width"] + this.options["unit"];
		for (var hCount = 0; hCount < hMaxCount; hCount++) {
			var h = hCount * this.options["hStep"];
			var rad = h / 360 * 2 * Math.PI;
			var x = (Math.cos(rad) + 1) * (this.dialogWidth / 2);
			var y = (1 - Math.sin(rad)) * (this.dialogWidth / 2);
			
			var left = x + this.options["unit"];
			var top = y + this.options["unit"];
			
			var hCell = new HColorCell(this, widthString, widthString, left, top, h);
			this.hSelecter.appendChild(hCell.element);
		}
	},
	
	_initializeCloseButton: function() {
		var button = document.createElement("div");
		button.innerHTML = "X";
		button.setAttribute("title", "close");
		button.style.position = "absolute";
		button.style.cursor = "pointer";
		button.style.fontFamily = "monospace";
		button.style.width = this.options["width"] + this.options["unit"];
		button.style.height = this.options["width"] + this.options["unit"];
		button.style.left = this.dialogWidth + this.options["unit"];
		button.style.top = "0" + this.options["unit"];
		button.style.zIndex = this.options["zIndex"] + 1;
		button.style.color = "#ffffff";
		button.style.backgroundColor = "#666666";
		button.style.textAlign = "center";
		button.style.lineHeight = this.options["width"] + this.options["unit"];
		Event.observe(button, 'click', this.hide.bindAsEventListener(this));
		return button;
	}

};

var HColorCell = Class.create();
HColorCell.prototype = {

	element: null,
	
	picker: null,
	
	hue: null,
	
	initialize: function(picker, width, height, left, top, h) {
		this.picker = picker;
		
		this.hue = h;
		var rgb = ColorUtil.hsvToRgb(h, 1, 1);
		var rgbString = ColorUtil.rgbToString(rgb[0], rgb[1], rgb[2]);
		
		this.element = document.createElement("div");
		this.element.style.position = "absolute";
		this.element.style.width = width;
		this.element.style.height = height;
		this.element.style.left = left;
		this.element.style.top = top;
		this.element.style.overflow = "hidden";
		this.element.style.zIndex = this.picker.dialog.style.zIndex + 1;
		this.element.style.backgroundColor = rgbString;

		if (this.picker.options["hueClick"] == true) {
			this.element.style.cursor = "pointer";
			Event.observe(this.element, "click", this._select.bindAsEventListener(this));
		} else {
			this.element.style.cursor = "normal";
			Event.observe(this.element, "mouseover", this._select.bindAsEventListener(this));
		}
	},
	
	_select: function() {
		this.picker.selectHue(this.hue);
	}

};

var SVColorCell = Class.create();
SVColorCell.prototype = {

	picker: null,

	element: null,
	
	hsv: null,
	
	rgb: null,

	initialize: function(picker, width, height, left, top, h, s, v) {
		this.picker = picker;
		
		this.hsv = Array(h, s, v);
		this.rgb = ColorUtil.hsvToRgb(this.hsv[0], this.hsv[1], this.hsv[2]);
		var rgbString = ColorUtil.rgbToString(this.rgb[0], this.rgb[1], this.rgb[2]);
		
		this.element = document.createElement("div");
		this.element.style.position = "absolute";
		this.element.style.cursor = "pointer";
		this.element.style.width = width;
		this.element.style.height = height;
		this.element.style.left = left;
		this.element.style.top = top;
		this.element.style.margin = "0px";
		this.element.style.padding = "0px";
		this.element.style.overflow = "hidden";
		this.element.style.zIndex = this.picker.dialog.style.zIndex + 1;
		this.element.style.backgroundColor = rgbString;
		this.element.setAttribute("title", rgbString);

		Event.observe(this.element, "mousedown", this._select.bindAsEventListener(this));
	},
	
	changeHue: function(h) {
		this.hsv = Array(h, this.hsv[1], this.hsv[2]);
		this.rgb = ColorUtil.hsvToRgb(this.hsv[0], this.hsv[1], this.hsv[2]);
		var rgbString = ColorUtil.rgbToString(this.rgb[0], this.rgb[1], this.rgb[2]);
		this.element.style.backgroundColor = rgbString;
		this.element.setAttribute("title", rgbString);
	},
	
	_select: function(event) {
		this.picker.selectColor(this.rgb[0], this.rgb[1], this.rgb[2]);
	}

};

