function SetColors(r,g,b,a) {
	ra=Math.round(r+(255-r)*grade1);
	ga=Math.round(g+(255-g)*grade1);
	ba=Math.round(b+(255-b)*grade1);

	rb=Math.round(r+(255-r)*grade2);
	gb=Math.round(g+(255-g)*grade2);
	bb=Math.round(b+(255-b)*grade2);

	rc=Math.round(r*grade3);
	gc=Math.round(g*grade3);
	bc=Math.round(b*grade3);

	rd=Math.round(r*grade4);
	gd=Math.round(g*grade4);
	bd=Math.round(b*grade4);

	colora="("+ra+","+ga+","+ba+")";
	colorb="("+rb+","+gb+","+bb+")";
	colorc="("+r+","+g+","+b+")";
	colord="("+rc+","+gc+","+bc+")";
	colore="("+rd+","+gd+","+bd+")";

	for (i=0;i<a.length;i+=2) {
		document.getElementById(a[i]+'c'+a[i+1]+'a').style.backgroundColor='rgb'+colora;
		document.getElementById(a[i]+'c'+a[i+1]+'b').style.backgroundColor='rgb'+colorb;
		document.getElementById(a[i]+'c'+a[i+1]+'c').style.backgroundColor='rgb'+colorc;
		document.getElementById(a[i]+'c'+a[i+1]+'d').style.backgroundColor='rgb'+colord;
		document.getElementById(a[i]+'c'+a[i+1]+'e').style.backgroundColor='rgb'+colore;
		
		document.getElementById(a[i]+'c'+a[i+1]+'a').innerHTML='#'+RGB2Hex(ra,ga,ba)+'<br>'+colora;
		document.getElementById(a[i]+'c'+a[i+1]+'b').innerHTML='#'+RGB2Hex(rb,gb,bb)+'<br>'+colorb;
		document.getElementById(a[i]+'c'+a[i+1]+'c').innerHTML='#'+RGB2Hex(r,g,b)+'<br>'+colorc;
		document.getElementById(a[i]+'c'+a[i+1]+'d').innerHTML='#'+RGB2Hex(rc,gc,bc)+'<br>'+colord;
		document.getElementById(a[i]+'c'+a[i+1]+'e').innerHTML='#'+RGB2Hex(rd,gd,bd)+'<br>'+colore;
	}
}

function HueShift(h,s) {
	h+=s;
	while (h>=360.0) h-=360.0;
	while (h<0.0) h+=360.0;
	return h;
}

function PutInRange(n,l,h) { return (n<l)?l:((n>h)?h:n); }

function SetHex(objid,val) {
	var thisval=Dec2Hex(val);
	eval('save'+objid+'="'+thisval+'"');
	document.getElementById(objid).value=thisval;
}

function SetDec(objid,val) {
	var thisval=Hex2Dec(val);
	eval('save'+objid+'="'+thisval+'"');
	document.getElementById(objid).value=thisval;
}

function DoKeyUp(obj) {
	thisid=obj.id;
	thisval=obj.value;
	if (thisval!=eval('save'+thisid)) {
		if (thisid=='ri') SetHex('rih',thisval);
		else if (thisid=='gi') SetHex('gih',thisval);
		else if (thisid=='bi') SetHex('bih',thisval);
		else if (thisid=='rih') SetDec('ri',thisval);
		else if (thisid=='gih') SetDec('gi',thisval);
		else if (thisid=='bih') SetDec('bi',thisval);
		eval('save'+thisid+'="'+thisval+'"');
		if (saveri.length && savegi.length && savebi.length && saveangle.length &&
			savegrade1.length && savegrade2.length && savegrade3.length && savegrade4.length)
		{
			running=running?2:1;
			while (running) {
				r=parseInt(saveri);
				g=parseInt(savegi);
				b=parseInt(savebi);
				angle=parseFloat(saveangle);
				grade1=PutInRange(parseFloat(savegrade1),0.0,1.0);
				grade2=PutInRange(parseFloat(savegrade2),0.0,1.0);
				grade3=PutInRange(parseFloat(savegrade3),0.0,1.0);
				grade4=PutInRange(parseFloat(savegrade4),0.0,1.0);
				if (running==2) { running=1; continue; }
				
				SetColors(r,g,b,Array('m','1','c','1','a','2','s','2','t','1'));
				if (running==2) { running=1; continue; }
				
				SetColors(g,b,r,Array('t','2'));
				if (running==2) { running=1; continue; }
				
				SetColors(b,r,g,Array('t','3'));
				if (running==2) { running=1; continue; }
				
				thisrgb=new Object();
				thisrgb.r=r;
				thisrgb.g=g;
				thisrgb.b=b;
				
				// complement
				temprgb=thisrgb;
				temphsv=RGB2HSV(temprgb);
				temphsv.hue=HueShift(temphsv.hue,180.0);
				temprgb=HSV2RGB(temphsv);
				SetColors(temprgb.r,temprgb.g,temprgb.b,Array('c','2'));
				if (running==2) { running=1; continue; }
				
				// analogous
				temprgb=thisrgb;
				temphsv=RGB2HSV(temprgb);
				temphsv.hue=HueShift(temphsv.hue,angle);
				temprgb=HSV2RGB(temphsv);
				SetColors(temprgb.r,temprgb.g,temprgb.b,Array('a','1'));
				if (running==2) { running=1; continue; }
				
				temprgb=thisrgb;
				temphsv=RGB2HSV(temprgb);
				temphsv.hue=HueShift(temphsv.hue,0.0-angle);
				temprgb=HSV2RGB(temphsv);
				SetColors(temprgb.r,temprgb.g,temprgb.b,Array('a','3'));
				if (running==2) { running=1; continue; }
				
				// split complementary
				temprgb=thisrgb;
				temphsv=RGB2HSV(temprgb);
				temphsv.hue=HueShift(temphsv.hue,180.0-angle);
				temprgb=HSV2RGB(temphsv);
				SetColors(temprgb.r,temprgb.g,temprgb.b,Array('s','1'));
				if (running==2) { running=1; continue; }
				
				temprgb=thisrgb;
				temphsv=RGB2HSV(temprgb);
				temphsv.hue=HueShift(temphsv.hue,180.0+angle);
				temprgb=HSV2RGB(temphsv);
				SetColors(temprgb.r,temprgb.g,temprgb.b,Array('s','3'));
				if (running==2) { running=1; continue; }
				
				running=0;
			}
		}
	}
}

hexdig='0123456789ABCDEF';
function Dec2Hex(d) {
	return hexdig.charAt((d-(d%16))/16)+hexdig.charAt(d%16);
}
function Hex2Dec(h) {
	h=h.toUpperCase();
	d=0;
	for (i=0;i<h.length;i++) {
		d=d*16;
		d+=hexdig.indexOf(h.charAt(i));
	}
	return d;
}

function RGB2Hex(r,g,b) {
	return Dec2Hex(r)+Dec2Hex(g)+Dec2Hex(b);
}

// RGB2HSV and HSV2RGB are based on Color Match Remix [http://color.twysted.net/]
// which is based on or copied from ColorMatch 5K [http://colormatch.dk/]
function HSV2RGB(hsv) {
	var rgb=new Object();
	if (hsv.saturation==0) {
		rgb.r=rgb.g=rgb.b=Math.round(hsv.value*2.55);
	} else {
		hsv.hue/=60;
		hsv.saturation/=100;
		hsv.value/=100;
		i=Math.floor(hsv.hue);
		f=hsv.hue-i;
		p=hsv.value*(1-hsv.saturation);
		q=hsv.value*(1-hsv.saturation*f);
		t=hsv.value*(1-hsv.saturation*(1-f));
		switch(i) {
		case 0: rgb.r=hsv.value; rgb.g=t; rgb.b=p; break;
		case 1: rgb.r=q; rgb.g=hsv.value; rgb.b=p; break;
		case 2: rgb.r=p; rgb.g=hsv.value; rgb.b=t; break;
		case 3: rgb.r=p; rgb.g=q; rgb.b=hsv.value; break;
		case 4: rgb.r=t; rgb.g=p; rgb.b=hsv.value; break;
		default: rgb.r=hsv.value; rgb.g=p; rgb.b=q;
		}
		rgb.r=Math.round(rgb.r*255);
		rgb.g=Math.round(rgb.g*255);
		rgb.b=Math.round(rgb.b*255);
	}
	return rgb;
}

function min3(a,b,c) { return (a<b)?((a<c)?a:c):((b<c)?b:c); }
function max3(a,b,c) { return (a>b)?((a>c)?a:c):((b>c)?b:c); }

function RGB2HSV(rgb) {
	hsv = new Object();
	max=max3(rgb.r,rgb.g,rgb.b);
	dif=max-min3(rgb.r,rgb.g,rgb.b);
	hsv.saturation=(max==0.0)?0:(100*dif/max);
	if (hsv.saturation==0) hsv.hue=0;
 	else if (rgb.r==max) hsv.hue=60.0*(rgb.g-rgb.b)/dif;
	else if (rgb.g==max) hsv.hue=120.0+60.0*(rgb.b-rgb.r)/dif;
	else if (rgb.b==max) hsv.hue=240.0+60.0*(rgb.r-rgb.g)/dif;
	if (hsv.hue<0.0) hsv.hue+=360.0;
	hsv.value=Math.round(max*100/255);
	hsv.hue=Math.round(hsv.hue);
	hsv.saturation=Math.round(hsv.saturation);
	return hsv;
}

saveri="0";
savegi="0";
savebi="0";
saverih="00";
savegih="00";
savebih="00";
saveangle="30.0";
savegrade1="0.6";
savegrade2="0.25";
savegrade3="0.667";
savegrade4="0.333";
running=0;

function ColorWheelInit() {
	document.getElementById('ri').onkeyup=function() { DoKeyUp(this); }
	document.getElementById('gi').onkeyup=function() { DoKeyUp(this); }
	document.getElementById('bi').onkeyup=function() { DoKeyUp(this); }
	document.getElementById('rih').onkeyup=function() { DoKeyUp(this); }
	document.getElementById('gih').onkeyup=function() { DoKeyUp(this); }
	document.getElementById('bih').onkeyup=function() { DoKeyUp(this); }
	document.getElementById('angle').onkeyup=function() { DoKeyUp(this); }
	document.getElementById('grade1').onkeyup=function() { DoKeyUp(this); }
	document.getElementById('grade2').onkeyup=function() { DoKeyUp(this); }
	document.getElementById('grade3').onkeyup=function() { DoKeyUp(this); }
	document.getElementById('grade4').onkeyup=function() { DoKeyUp(this); }
	DoKeyUp(document.getElementById('grade4'));
}

window.onload=function() { ColorWheelInit(); }
