//This code originally from http://ecritters.biz/colorselector/
// Published under a BSD license
// Syntactical sugar by Mark Maunder <mark@linebuzz.com>
function RGB2HEX(rgb){
	if(/^rgb\(/i.test(rgb)){
		rgb = rgb.replace(/rgb\(/i, '');
		rgb = rgb.replace(/\)/, '');
		rgb = rgb.replace(/\s+/g, '');
		var colors = rgb.split(',');
		return ColorSelector.prototype.rgbToHex(colors[0] / 255, colors[1] / 255, colors[2] / 255, true);
	} else {
		return rgb;
	}
}
var CURRENT_COLOR_SELECTOR = false;
var ColorSelector = Class.create();
ColorSelector.prototype = {
	initialize: function(x, y, initialColor, onApply){
		if(CURRENT_COLOR_SELECTOR){
			CURRENT_COLOR_SELECTOR.close();
		}
		CURRENT_COLOR_SELECTOR = this;
		
		this.hideSelectsIfIE6();

		this.initialColor = RGB2HEX(initialColor);
		this.onApply = onApply;	
		this.CROSSHAIRS_LOCATION = 'http://feedjit.com/images/colorselector/crosshairs.png';
		this.HUE_SLIDER_LOCATION = 'http://feedjit.com/images/colorselector/h.png';
		this.HUE_SLIDER_ARROWS_LOCATION = 'http://feedjit.com/images/colorselector/position.png';
		this.SAT_VAL_SQUARE_LOCATION = 'http://feedjit.com/images/colorselector/sv.png';
		this.arVersion = navigator.appVersion.split("MSIE");
		this.version = parseFloat(this.arVersion[1]);

		this.huePositionImg = document.createElement('img');
		this.huePositionImg.galleryImg = false;
		this.huePositionImg.width = 35;
		this.huePositionImg.height = 11;
		this.huePositionImg.src = this.HUE_SLIDER_ARROWS_LOCATION;
		this.huePositionImg.style.position = 'absolute';

		this.hueSelectorImg = document.createElement('img');
		this.hueSelectorImg.galleryImg = false;
		this.hueSelectorImg.width = 35;
		this.hueSelectorImg.height = 200;
		this.hueSelectorImg.src = this.HUE_SLIDER_LOCATION;
		this.hueSelectorImg.style.display = 'block';

		this.satValImg = document.createElement('img');
		this.satValImg.galleryImg = false;
		this.satValImg.width = 200;
		this.satValImg.height = 200;
		this.satValImg.src = this.SAT_VAL_SQUARE_LOCATION;
		this.satValImg.style.display = 'block';

		this.crossHairsImg = document.createElement('img');
		this.crossHairsImg.galleryImg = false;
		this.crossHairsImg.width = 21;
		this.crossHairsImg.height = 21;
		this.crossHairsImg.src = this.CROSSHAIRS_LOCATION;
		this.crossHairsImg.style.position = 'absolute';


		var wSize = this.getWindowSize();
		wSize.x -= 20;
		var pLeft = x;
		var pTop = y - 290;
		if(pLeft + 290 > wSize.x){
			pLeft = wSize.x - 290;
		}
		if(pTop < 1){
			pTop = 1;
		}
		var pDiv = document.createElement('DIV');
		pDiv.style.position = 'absolute';
		pDiv.style.width = '290px';
		pDiv.style.height = '290px';
		pDiv.style.left = pLeft + 'px';
		pDiv.style.top = pTop + 'px';
		pDiv.style.zIndex = 1000000;
		pDiv.style.backgroundColor = '#CCC';
		pDiv.style.border = '1px solid #000';
		this.pDiv = pDiv;
		
		this.div = this.makeColorSelector();
		this.pDiv.appendChild(this.div);
		document.body.appendChild(this.pDiv);
	},
	isIE6: function(){
		var rv = -1; // Return value assumes failure.
		if (navigator.appName == 'Microsoft Internet Explorer')
		{
			var ua = navigator.userAgent;
			var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
			if (re.exec(ua) != null)
				rv = parseFloat( RegExp.$1 );
		}
		return rv > -1 && rv < 7;
	},
	hideSelectsIfIE6: function(){
		if(this.isIE6()){
			['traf', 'pop', 'map', 'col'].each(function(key){
				var el = $('colorScheme_' + key);
				if(el){
					el.style.display = 'none';
				}
				});
		}
	},
	showSelectsIfIE6: function(){
		if(this.isIE6()){
			['traf', 'pop', 'map', 'col'].each(function(key){		
				var el = $('colorScheme_' + key);
				if(el){
					el.style.display = 'inline';
				}
				});

		}
	},
	close: function(){
		this.satValObserver.stopObserving();
		this.hueObserver.stopObserving();
		this.pDiv.parentNode.removeChild(this.pDiv);
		this.showSelectsIfIE6();
		CURRENT_COLOR_SELECTOR = false;
	},
	apply: function(){
		if(this.onApply){
			this.onApply(this.inputBox.value);
		}
		this.close();
	},
	getWindowSize: function() {
		var myWidth = 0, myHeight = 0;
		if( typeof( window.innerWidth ) == 'number' ) {
			//Non-IE
			myWidth = window.innerWidth;
			myHeight = window.innerHeight;
		} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
			//IE 6+ in 'standards compliant mode'
			myWidth = document.documentElement.clientWidth;
			myHeight = document.documentElement.clientHeight;
		} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
			//IE 4 compatible
			myWidth = document.body.clientWidth;
			myHeight = document.body.clientHeight;
		}
		return { x: myWidth, y: myHeight };
	},
	hexToRgb: function(hex_string, default_){
	    if (default_ == undefined)
	    {
		default_ = null;
	    }

	    if (hex_string.substr(0, 1) == '#')
	    {
		hex_string = hex_string.substr(1);
	    }
	    
	    var r;
	    var g;
	    var b;
	    if (hex_string.length == 3)
	    {
		r = hex_string.substr(0, 1);
		r += r;
		g = hex_string.substr(1, 1);
		g += g;
		b = hex_string.substr(2, 1);
		b += b;
	    }
	    else if (hex_string.length == 6)
	    {
		r = hex_string.substr(0, 2);
		g = hex_string.substr(2, 2);
		b = hex_string.substr(4, 2);
	    }
	    else
	    {
		return default_;
	    }
	    
	    r = parseInt(r, 16);
	    g = parseInt(g, 16);
	    b = parseInt(b, 16);
	    if (isNaN(r) || isNaN(g) || isNaN(b))
	    {
		return default_;
	    }
	    else
	    {
		return {r: r / 255, g: g / 255, b: b / 255};
	    }
	},
	rgbToHex: function(r, g, b, includeHash){
		r = Math.round(r * 255);
		g = Math.round(g * 255);
		b = Math.round(b * 255);
		if (includeHash == undefined)
		{
			includeHash = true;
		}
		r = r.toString(16);
		if (r.length == 1)
		{
			r = '0' + r;
		}
		g = g.toString(16);
		if (g.length == 1)
		{
			g = '0' + g;
		}
		b = b.toString(16);
		if (b.length == 1)
		{
			b = '0' + b;
		}
		return ((includeHash ? '#' : '') + r + g + b).toUpperCase();
	},
	fixPNG: function(myImage){
	    if ((this.version >= 5.5) && (this.version < 7) && (document.body.filters)) 
	    {
		var node = document.createElement('span');
		node.id = myImage.id;
		node.className = myImage.className;
		node.title = myImage.title;
		node.style.cssText = myImage.style.cssText;
		node.style.setAttribute('filter', "progid:DXImageTransform.Microsoft.AlphaImageLoader"
						+ "(src=\'" + myImage.src + "\', sizingMethod='scale')");
		node.style.fontSize = '0';
		node.style.width = myImage.width.toString() + 'px';
		node.style.height = myImage.height.toString() + 'px';
		node.style.display = 'inline-block';
		return node;
	    }
	    else
	    {
		return myImage.cloneNode(false);
	    }
	},

// This copyright statement applies to the following two functions,
// which are taken from MochiKit.
//
// Copyright 2005 Bob Ippolito <bob@redivi.com>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject
// to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

	hsvToRgb: function(hue, saturation, value){
	    var red;
	    var green;
	    var blue;
	    if (value == 0.0)
	    {
		red = 0;
		green = 0;
		blue = 0;
	    }
	    else
	    {
		var i = Math.floor(hue * 6);
		var f = (hue * 6) - i;
		var p = value * (1 - saturation);
		var q = value * (1 - (saturation * f));
		var t = value * (1 - (saturation * (1 - f)));
		switch (i)
		{
		    case 1: red = q; green = value; blue = p; break;
		    case 2: red = p; green = value; blue = t; break;
		    case 3: red = p; green = q; blue = value; break;
		    case 4: red = t; green = p; blue = value; break;
		    case 5: red = value; green = p; blue = q; break;
		    case 6: // fall through
		    case 0: red = value; green = t; blue = p; break;
		}
	    }
	    return {r: red, g: green, b: blue};
	},
	rgbToHsv: function(red, green, blue){
	    var max = Math.max(Math.max(red, green), blue);
	    var min = Math.min(Math.min(red, green), blue);
	    var hue;
	    var saturation;
	    var value = max;
	    if (min == max)
	    {
		hue = 0;
		saturation = 0;
	    }
	    else
	    {
		var delta = (max - min);
		saturation = delta / max;
		if (red == max)
		{
		    hue = (green - blue) / delta;
		}
		else if (green == max)
		{
		    hue = 2 + ((blue - red) / delta);
		}
		else
		{
		    hue = 4 + ((red - green) / delta);
		}
		hue /= 6;
		if (hue < 0)
		{
		    hue += 1;
		}
		if (hue > 1)
		{
		    hue -= 1;
		}
	    }
	    return {
		h: hue,
		s: saturation,
		v: value
	    };
	},
	makeColorSelector: function(){
	    var rgb, hsv;
	    var inputBox = document.createElement('INPUT');
	    inputBox.type = 'text';
	    inputBox.value = this.initialColor;
	    inputBox.style.position = 'absolute';
	    inputBox.style.left = '76px';
	    inputBox.style.fontSize = '16px';
	    inputBox.style.fontFamily = 'Arial, Verdana';
	    inputBox.style.padding = '3px';
	    inputBox.style.margin = '0px';
	    inputBox.size = 7;
	    inputBox.style.top = (200 + (25 - (inputBox.offsetHeight/2))).toString() + 'px';
	    this.inputBox = inputBox;
	    var colorChanged = function(){
		var hex = this.rgbToHex(rgb.r, rgb.g, rgb.b);
		var hueRgb = this.hsvToRgb(hsv.h, 1, 1);
		var hueHex = this.rgbToHex(hueRgb.r, hueRgb.g, hueRgb.b);
		previewDiv.style.background = hex;
		inputBox.value = hex;
		satValDiv.style.background = hueHex;
		crossHairs.style.left = ((hsv.v*199)-10).toString() + 'px';
		crossHairs.style.top = (((1-hsv.s)*199)-10).toString() + 'px';
		huePos.style.top = ((hsv.h*199)-5).toString() + 'px';
	    }.bind(this);
	    var rgbChanged = function(){
		hsv = this.rgbToHsv(rgb.r, rgb.g, rgb.b);
		colorChanged();
	    }.bind(this);
	    var hsvChanged = function(){
		rgb = this.hsvToRgb(hsv.h, hsv.s, hsv.v);
		colorChanged();
	    }.bind(this);
	    
	    var colorSelectorDiv = document.createElement('div');
	    colorSelectorDiv.style.padding = '15px';
	    colorSelectorDiv.style.position = 'relative';
	    colorSelectorDiv.style.height = '275px';
	    colorSelectorDiv.style.width = '250px';
    
	    var satValDiv = document.createElement('div');
	    satValDiv.style.position = 'relative';
	    satValDiv.style.width = '198px'; //198 because of 1 px border on all sides - see satValDragged
	    satValDiv.style.height = '198px';
	    satValDiv.style.borderStyle = 'inset';
	    satValDiv.style.borderColor = '#CCC';
	    satValDiv.style.borderWidth = '1px';

	    var newSatValImg = this.fixPNG(this.satValImg);
	    satValDiv.appendChild(newSatValImg);
	    var crossHairs = this.crossHairsImg.cloneNode(false);
	    satValDiv.appendChild(crossHairs);
	    var satValDragged = function(x, y){
		hsv.s = 1-(y/199);
		hsv.v = (x/199);
		hsvChanged();
	    }.bind(this);
	    this.satValObserver = new DragObserver(satValDiv, satValDragged)
	    colorSelectorDiv.appendChild(satValDiv);

	    var hueDiv = document.createElement('div');
	    hueDiv.style.position = 'absolute';
	    hueDiv.style.left = '230px';
	    hueDiv.style.top = '15px';
	    hueDiv.style.width = '35px';
	    hueDiv.style.height = '200px';
	    hueDiv.style.borderStyle = 'inset';
	    hueDiv.style.borderColor = '#CCC';
	    hueDiv.style.borderWidth = '1px';

	    var huePos = this.fixPNG(this.huePositionImg);
	    hueDiv.appendChild(this.hueSelectorImg.cloneNode(false));
	    hueDiv.appendChild(huePos);
	    var hueDragged = function(x, y){
		hsv.h = y/199;
		hsvChanged();
	    }.bind(this);
	    this.hueObserver = new DragObserver(hueDiv, hueDragged);
	    colorSelectorDiv.appendChild(hueDiv);
	    
	    var previewDiv = document.createElement('div');
	    previewDiv.style.height = '25px'
	    previewDiv.style.width = '50px';
	    previewDiv.style.position = 'absolute';
	    previewDiv.style.top = '225px';
	    previewDiv.style.left = '15px';
	    previewDiv.style.borderStyle = 'inset';
	    previewDiv.style.borderWidth = '1px 1px 0px 1px';
	    previewDiv.style.borderColor = '#CCC';
	    colorSelectorDiv.appendChild(previewDiv);

	    var originalColorDiv = document.createElement('div');
	    originalColorDiv.style.height = '25px'
	    originalColorDiv.style.width = '50px';
	    originalColorDiv.style.position = 'absolute';
	    originalColorDiv.style.top = '251px';
	    originalColorDiv.style.left = '15px';
	    originalColorDiv.style.borderStyle = 'inset';
	    originalColorDiv.style.borderWidth = '0px 1px 1px 1px';
	    originalColorDiv.style.borderColor = '#CCC';
	    originalColorDiv.style.backgroundColor = this.initialColor;
	    colorSelectorDiv.appendChild(originalColorDiv);


	    var sButton = document.createElement('input');
	    sButton.type = 'button';
	    sButton.value = 'Apply';
	    sButton.style.position = 'absolute';
	    sButton.style.right = '5px';
	    sButton.style.top = '230px';
	    sButton.style.width = '80px';
	    sButton.style.fontFamily = 'Arial, Verdana';
	    sButton.style.fontSize = '16px';
	    sButton.style.padding = '0px';
	    sButton.onclick = this.apply.bind(this);
	    colorSelectorDiv.appendChild(sButton);
	    
	    var cButton = document.createElement('input');
	    cButton.type = 'button';
	    cButton.value = 'Cancel';
	    cButton.style.position = 'absolute';
	    cButton.style.right = '5px';
	    cButton.style.top = '260px';
	    cButton.style.width = '80px';
	    cButton.style.fontFamily = 'Arial, Verdana';
	    cButton.style.fontSize = '16px';
	    cButton.style.padding = '0px';
	    cButton.onclick = function(){ this.close(); }.bind(this);
	    colorSelectorDiv.appendChild(cButton);
    
	   
	   this.inputBoxChangedListener = function(){
		rgb = this.hexToRgb(inputBox.value, {r: 0, g: 0, b: 0});
		rgbChanged();
	    }.bind(this);
	    Event.observe(inputBox, 'change', this.inputBoxChangedListener, false);
	    Event.observe(inputBox, 'keydown', function(e){ if(e.keyCode == 13){ this.inputBoxChangedListener(); } }.bindAsEventListener(this), false);

	    colorSelectorDiv.appendChild(inputBox);
	    
	    this.inputBoxChangedListener();
	    
	    return colorSelectorDiv;
	}
};

var DragObserver = Class.create();
DragObserver.prototype = {
	initialize: function(node, handler){
		this.handler = handler;
		this.node = node;
		
		this.mouseDownListener = this.mouseDown.bindAsEventListener(this);
		this.moveListener = this.move.bindAsEventListener(this);
		this.upListener = this.up.bindAsEventListener(this);


		Event.observe(node, 'mousedown', this.mouseDownListener, false);
		node.onmousedown = function(e) { return false; };
		node.onselectstart = function(e) { return false; };
		node.ondragstart = function(e) { return false; };
	},
	stopObserving: function(){
		Event.stopObserving(document, 'mouseup', this.upListener, false);
		Event.stopObserving(document, 'mousemove', this.moveListener, false);
		Event.stopObserving(this.node, 'mousedown', this.mouseDownListener, false);
	},
	pageCoords: function(node){
	    var x = node.offsetLeft;
	    var y = node.offsetTop;
	    var parent = node.offsetParent;
	    while (parent != null)
	    {
		x += parent.offsetLeft;
		y += parent.offsetTop;
		parent = parent.offsetParent;
	    }
	    return {x: x, y: y};
	},

	fixCoords: function(x, y){
		var nodePageCoords = this.pageCoords(this.node);
		x = (x - nodePageCoords.x) + document.documentElement.scrollLeft;
		y = (y - nodePageCoords.y) + document.documentElement.scrollTop;
		if (x < 0) x = 0;
		if (y < 0) y = 0;
		if (x > this.node.offsetWidth - 1) x = this.node.offsetWidth - 1;
		if (y > this.node.offsetHeight - 1) y = this.node.offsetHeight - 1;
		return {x: x, y: y};
	},
	move: function(ev){
		var coords = this.fixCoords(ev.clientX, ev.clientY);
		if (coords.x != this.lastX || coords.y != this.lastY){
			this.lastX = coords.x;
			this.lastY = coords.y;
			this.handler(coords.x, coords.y);
		}
	},
	up: function(ev){
		Event.stopObserving(document, 'mouseup', this.upListener, false);
		Event.stopObserving(document, 'mousemove', this.moveListener, false);
		Event.observe(this.node, 'mousedown', this.mouseDownListener, false);
	},
	mouseDown: function(ev){
		var coords = this.fixCoords(ev.clientX, ev.clientY);
		this.lastX = coords.x;
		this.lastY = coords.y;
		this.handler(coords.x, coords.y);

		Event.observe(document, 'mouseup', this.upListener, false);
		Event.observe(document, 'mousemove', this.moveListener, false);
		Event.stopObserving(this.node, 'mousedown', this.mouseDownListener, false);
		Event.stop(ev);
		//if (ev.preventDefault) ev.preventDefault();
	}
};
