$(".colour_selector").ready(function() {
	$(".colour_selector").each(function(i) {
		//controls
		var colour_chooser = $(this).find(".colour_chooser");
		var brightness_changer = $(this).find(".brightness_changer");
		var colour_preview = $(this).find(".colour_preview");
		var hue_image = colour_chooser.find(".hue_image");
		var colour_cursor = colour_chooser.find(".colour_cursor");
		var brightness_cursor = brightness_changer.find(".brightness_cursor");
		
		var span_red_value = $(this).find(".red_value");
		var span_green_value = $(this).find(".green_value");
		var span_blue_value = $(this).find(".blue_value");
		
		//variables
		var lightness = 1.0, hue = 0.0, saturation = 0.0;
		var red=0, green=0, blue=0;
		var mouseDown = false;
		
		//when ready
		updateColourDisplay();
		
		//methods
		brightness_changer.select(function() { $(this).blur(); });
		brightness_changer.bind("mousedown",function(event) { mouseDown=true; changeBrightness(event, $(this)); });
		brightness_changer.find(".drag_plane").bind("mousemove",function(event) { if (mouseDown) changeBrightness(event, $(this)); });
		brightness_changer.bind("mouseup",function() { mouseDown=false; });

		function changeBrightness(mouseEvent, obj) {
			yPos = (mouseEvent.pageY-obj.offset().top);
			if (yPos<0) yPos=0;
			if (yPos>obj.height()) yPos=obj.height();
			
			brightness_cursor.css("top", yPos);
			
			lightness = (yPos/obj.height());
			
			var newColour = Math.floor(lightness*256.0);
			colour_chooser.css("background-color","rgb(" + newColour + "," + newColour + "," + newColour + ")");
			hue_image.css("opacity", lightness);
			
			updateColourDisplay();
		}

		colour_chooser.bind("mousedown" ,function(event) { mouseDown=true; changeColour(event, $(this)); });
		colour_chooser.find(".drag_plane").bind("mousemove" ,function(event) { if (mouseDown) changeColour(event, $(this)); });
		colour_chooser.bind("mouseup" ,function(event) { mouseDown=false; });
		
		function changeColour(mouseEvent, obj) {
			xPos = (mouseEvent.pageX-obj.offset().left);
			yPos = (mouseEvent.pageY-obj.offset().top);
			
			colour_cursor.css("top", yPos);
			colour_cursor.css("left", xPos);

			hue = (xPos/obj.width()) * 360.0
			saturation = yPos/obj.height();
			
			updateColourDisplay();
		}
		
		function updateColourDisplay() {
			var newColour = hsvToRGB(hue, saturation, lightness);
			red = newColour[0];
			green = newColour[1];
			blue = newColour[2];
			
			colour_preview.css("background-color", "rgb(" + red + "," + green + "," + blue + ")");
			
			span_red_value.text(red);
			span_green_value.text(green);
			span_blue_value.text(blue);
		}
	});
});

function hsvToRGB(hue, saturation, value) {
	var newColour = new Array(3);
	var temp = hue/60.0;
	var hueRange = Math.floor(temp) % 6;
	var hueRemainder = temp - Math.floor(temp);
	
	var part1 = Math.floor(value * (1.0-saturation) * 256.0);
	var part2 = Math.floor(value * (1.0- hueRemainder*saturation) * 256.0);
	var part3 = Math.floor(value * (1.0-(1.0-hueRemainder)*saturation) * 256.0);
	var value = Math.floor(value * 256.0);
	
	switch (hueRange) {
		case 0: newColour=[value,part3,part1]; break;
		case 1: newColour=[part2,value,part1]; break;
		case 2: newColour=[part1,value,part3]; break;
		case 3: newColour=[part1,part2,value]; break;
		case 4: newColour=[part3,part1,value]; break; 
		case 5: default: newColour=[value,part1,part2];
	}
	
	return newColour;
}