/****************************************************************************************************/
/** Code for the colour picker goes here *************************************************************/
/****************************************************************************************************/
//xxx;todo: seperate the code for the colour picker into its own js file
// Global object to hold drag information.

var dragObj = new Object();
dragObj.zIndex = 0;

function dragGo(event) {

	var x, y;

	// Get cursor position with respect to the page.
	if (window.ActiveXObject) {
		x = window.event.clientX + document.documentElement.scrollLeft
		  + document.body.scrollLeft;
	} else {
		x = event.clientX + window.scrollX;
	}

  	// Move drag element by the same amount the cursor has moved.
	dragObj.colour.value = (dragObj.elStartLeft + x - dragObj.cursorStartX);

	if(dragObj.colour.value < 255) {
  		if (dragObj.colour.value > 0){
	  		dragObj.elNode.style.left = (dragObj.elStartLeft + x - dragObj.cursorStartX) + "px";
	  	} else {
  			dragObj.elNode.style.left = '0px';
			dragObj.colour.value = 0;
	  	}
  	} else {
		dragObj.elNode.style.left = '255px';
		dragObj.colour.value = 255;
  	}

	dragObj.colour.RGBInput.setValue(dragObj.colour.value);

  	dragObj.colour.parent.refreshValue();
  	dragObj.colour.parent.updateBound();


	if(window.event) {
		window.event.cancelBubble = true;
		window.event.returnValue = false;
	} else {
		event.preventDefault();
	}
}

function dragStop(event) {

  // Stop capturing mousemove and mouseup events.

  if (document.detachEvent) {
    document.detachEvent("onmousemove", dragGo);
    document.detachEvent("onmouseup",   dragStop);
  } else if(document.removeEventListener) {
    document.removeEventListener("mousemove", dragGo,   true);
    document.removeEventListener("mouseup",   dragStop, true);
  }
}


/*********************************************************/
/*** Utility Functions ***********************************/
/*********************************************************/

function decToHex( val ) {
	return val.toString(16).toUpperCase();
}

function hexToDec( val ) {
	return parseInt(val, 16);
}

padLeft = function(aString, aChar, count) {
	while(aString.length<count) {
		aString = aChar + aString;
	}

	return aString;
}


/*********************************************************/
/*** Colour Picker ***************************************/
/*********************************************************/
function ColourPickerRGBInput(colour) {
	this.colourPickerColour = colour;
	this.colourPicker = this.colourPickerColour.parent;
	this.inputId = 'colourPickerRGBInput_'
		+ this.colourPickerColour.colour + '_' 
		+ this.colourPickerColour.parent.id;
}

ColourPickerRGBInput.prototype.getHTML = function() {

	var prefix = (this.colourPickerColour.parent.CSSDocument) ? this.colourPickerColour.parent.CSSDocument.id + '_': '';
	
	return '<input id="'
		+ this.inputId
		+ '" maxsize="2" value="' 
		+ this.colourPickerColour.value + '" size="2" '
		+ ' onchange="window[\'' + prefix + this.colourPickerColour.parent.id +  '\'].' + this.colourPickerColour.colour + '.RGBInput.change(event)" '
		+'/>';
}

ColourPickerRGBInput.prototype.setValue = function(val) {
	var input = this.colourPicker.getElementById(this.inputId);
	if(input) {
		input.value = val;
	}
}

ColourPickerRGBInput.prototype.change = function(e) {
	var input = this.colourPicker.getElementById(this.inputId);
	var val = parseInt(input.value, 10);
	if(isNaN(val) || val.toString() != input.value || val < 0 || val > 255) {
		alert('You need to enter a value between 0 and 255');
		input.select();
		input.focus();
		e.returnValue = false;
	} else {
		this.colourPickerColour.setValue(val);
  		this.colourPickerColour.parent.refreshValue();
  		this.colourPickerColour.parent.updateBound();
  	}
}

function ColourPickerColour(parent, colour, value) {
	this.parent = parent;
	this.colour = colour;
	this.value = value;
	this.RGBInput = new ColourPickerRGBInput(this);
}

ColourPickerColour.prototype.getValue = function() {
	return this.value;
}

ColourPickerColour.prototype.buttonDragStart = function(event) {

  var el;
  var x, y;

  dragObj.elNode = this.getButtonObject();
  dragObj.colour = this;

  // Get cursor position with respect to the page.

  if (window.event) {
    x = window.event.clientX + document.documentElement.scrollLeft
      + document.body.scrollLeft;
  } else {
    x = event.clientX + window.scrollX;
  }

  // Save starting positions of cursor and element.

  dragObj.cursorStartX = x;
  dragObj.elStartLeft  = parseInt(dragObj.elNode.style.left, 10);

  if (isNaN(dragObj.elStartLeft)) dragObj.elStartLeft = 0;


  // Capture mousemove and mouseup events on the page.
  if (window.event) {
    document.attachEvent("onmousemove", dragGo);
    document.attachEvent("onmouseup",   dragStop);
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  } else if (document.addEventListener) {
    document.addEventListener("mousemove", dragGo,   true);
    document.addEventListener("mouseup",   dragStop, true);
    event.preventDefault();
  } 
}

ColourPickerColour.prototype.getButtonObject = function(){
	return this.parent.getElementById('colourPickerButton'	+ this.colour +'_' + this.parent.id);
}

ColourPickerColour.prototype.getHTML = function() {

	var prefix = (this.parent.CSSDocument) ? this.parent.CSSDocument.id + '_': '';
	var out =  '    <td align="right">' 
		+ this.RGBInput.getHTML() 
		+ '</td><td><div class="colourPickerSliderCol colourPicker' + this.colour 
		+ '" id="colourPicker_'
		+ this.colour +'_' + this.parent.id + '">'
		+ '<div id="colourPickerButton'
		+ this.colour +'_' + this.parent.id
		+ '" class="colourPickerSliderButton" onmousedown="window[\'' + prefix + this.parent.id +  '\'].' 
		+ this.colour + '.buttonDragStart(event)"'
		+ '><div>&#160;</div></div>'

		+ '</div></td>\r\n';
	return out;
}

ColourPickerColour.prototype.setValue = function(value) {
	this.value = value;

	this.RGBInput.setValue(value);
	var button = this.getButtonObject();
	if(button) {
		button.style.left = value + "px";
	}
}

/*****************************************************************
* ColourPicker class.
*****************************************************************/
function ColourPicker (id, node){
	this.id = id;
	this.node = node;
	window[id] = this;
	this.red = new ColourPickerColour(this, "red", 0);
	this.green = new ColourPickerColour(this, "green", 0);
	this.blue = new ColourPickerColour(this, "blue", 0);
}

ColourPicker.prototype.getValue = function() {
	return padLeft(decToHex(this["red"].getValue()), '0', 2)
		+ padLeft(decToHex(this["green"].getValue()), '0', 2)
		+ padLeft(decToHex(this["blue"].getValue()), '0', 2);
}

ColourPicker.prototype.change = function(e) {
	var input = this.getElementById('colourPickerText_' + this.id);
	var colour = input.value;
	colour = colour.replace('#', '');
	if (colour.length == 3) {
	    colour = colour.substr(0,1) + colour.substr(0,1) + 
	                colour.substr(1,1) + colour.substr(1,1) + 
	                colour.substr(2,1) + colour.substr(2,1);
	}
	var val = parseInt(colour, 16);
	if(isNaN(val) || val > parseInt('FFFFFF', 16) || val < 0 || padLeft(decToHex(val),'0',6).toUpperCase() != colour.toUpperCase()) {
		alert('You need to enter a valid RGB number between 000000 and FFFFFF');
		input.select();
		input.focus();
		e.returnValue = false;
	} else {
		this.setValue('#' + colour);
		this.updateBound();
	}
}

ColourPicker.prototype.getHTML = function() {
	return '<table cellpadding="0" cellspacing="0" class="colourPicker" id="colourPicker_' + this.id + '">'
		+ '<tr><td class="colourPickerText" colspan="3" ' 
		+ '>#<input id="colourPickerText_' + this.id 
		+ '" size="6" value="' + this.getValue() 
		+ '" onchange="window[\'' + this.id + '\'].change(event)" /><br/>&nbsp;</td></tr>'
		+ '<tr><td rowspan="4"><div class="colourPickerPreview" id="colourPickerPreview_' + this.id + '" >&#160;</div></td>' 
		+  this.red.getHTML() + '</tr>'
		+ '<tr>' + this.green.getHTML() + '</tr>'
		+ '<tr>' + this.blue.getHTML() + '</tr>'
		+ '</table>'; 
}

ColourPicker.prototype.getElementById = function(id) {
	var element = window[id];
	if(!element)  element = document.getElementById(id);
	return element;
}

ColourPicker.prototype.refreshValue = function() {
	var inputElement = this.getElementById('colourPickerText_' + this.id);
	inputElement.value = this.getValue();

	var previewElement = this.getElementById('colourPickerPreview_' + this.id);
	previewElement.style.backgroundColor = '#' + inputElement.value;
}

ColourPicker.prototype.setValue = function(value) {
	this.red.setValue(hexToDec(value.substring(1,3)));
	this.green.setValue(hexToDec(value.substring(3,5)));
	this.blue.setValue(hexToDec(value.substring(5,7)));

	this.refreshValue();
}

ColourPicker.prototype.updateBound = function() {

	if(this.node) {
		this.node.domNode.firstChild.nodeValue = '#' + this.getValue();
		this.node.cssBuilder.updateHidden();
	} else {
		if(this.updateObject && this.updateObject.setValue) {
			this.updateObject.setValue( '#' + this.getValue() );
			if(this.CSSDocument) {
				this.CSSDocument.updateBound();
			}
		}
	}
}
