function pagePart()
{
this.hex="000000";
this.red = 0;
this.green = 0;
this.blue = 0;
this.hue = 0;
this.saturation = 0;
this.brightness = 0;
this.y = 0;
}

var background = new pagePart();
var text = new pagePart();
var vlink = new pagePart();
var link = new pagePart();
var backgroundTV = new pagePart();
var textTV = new pagePart();
var vlinkTV = new pagePart();
var linkTV = new pagePart();

background.hex = "000000";
backgroundTV.hex = "000000";
text.hex = "E6E6E6"; 
link.hex = "3434FF";
vlink.hex = "CC33FF";
textTV.hex = "E6E6E6";
linkTV.hex = "3434FF";
vlinkTV.hex = "CC33FF";

function loadColorsPages()
{
    parent.frames.tvColor.location = "tvColor.html";
	parent.frames.theirColor.location = "theirColor.html";
	parent.loaded = 1;
}

function setPropertiesFromRGB(someObject)

{
	someObject.red = parseInt(parent.frames.selBoxes.document.ColorForm.r.value);
	someObject.green = parseInt(parent.frames.selBoxes.document.ColorForm.g.value);
	someObject.blue = parseInt(parent.frames.selBoxes.document.ColorForm.b.value);
	RGBtoHSB(someObject);
}

function setPropertiesFromHSB(someObject)

{
	someObject.hue = parent.frames.selBoxes.document.ColorForm.h.value;
	someObject.saturation = parent.frames.selBoxes.document.ColorForm.s.value;
	someObject.brightness = parent.frames.selBoxes.document.ColorForm.v.value;
	HSBtoRGB(someObject);
}

function setPropertiesFromHex(someObject)
{
	someObject.red = parseInt(someObject.hex.substring(0,2),16);
	someObject.green = parseInt(someObject.hex.substring(2,4),16);
	someObject.blue = parseInt(someObject.hex.substring(4,6),16);
	RGBtoHSB(someObject);
	setYfromRGB(someObject);
}

function populateRGB(someObject)//Make sure user-entered values are "sticky".
{
	setPropertiesFromHex(someObject);
	parent.frames.selBoxes.document.ColorForm.r.value = someObject.red;
	parent.frames.selBoxes.document.ColorForm.g.value = someObject.green;
	parent.frames.selBoxes.document.ColorForm.b.value = someObject.blue;
	parent.frames.selBoxes.document.ColorForm.theirHex.value = someObject.hex;
	if (parent.frames[1].location == "http://surfin.spies.com/~jos/spiesWeb/web/webtv/RevisedColorpick2/moreOptions.html")
	{
		parent.frames.selBoxes.document.ColorForm.h.value = someObject.hue;
		parent.frames.selBoxes.document.ColorForm.s.value = someObject.saturation;
		parent.frames.selBoxes.document.ColorForm.v.value = someObject.brightness;
		parent.frames.selBoxes.document.ColorForm.Y.value = someObject.y;
	}
}

function setYfromRGB(someObject)
{
    someObject.y = Math.round(.299*someObject.red+.587*someObject.green+.114*someObject.blue);
}

function returnY(red, green, blue)
{
    return Math.round(.299*red+.587*green+.114*blue);
}

function change()
{
	parent.frames.theirColor.location = "theirColor.html";
	doTVstuff();
}
function RGBchange(formField)
{
	checkColor(formField);
    setPropertiesFromRGB(getChoice());
    populateRGB(getChoice());
}

function HSBchange(formField)
{
    checkColor(formField);
	setPropertiesFromHSB(getChoice());
	populateRGB(getChoice());
}

function hexChange(hexValue)
{
	checkTheirHex(hexValue);
	getChoice().hex = hexValue;
	setPropertiesFromHex(getChoice());
	populateRGB(getChoice());
}

function doTVstuff()
{
	cloneTheirColor(background, backgroundTV); //Lame hack so we can make "backgroundTV an input in the function below.
	cloneTheirColor(text, textTV); //Lame hack
	cloneTheirColor(link, linkTV);
	cloneTheirColor(vlink, vlinkTV);
	checkForBrightWhites(backgroundTV);
	fixYtextBack();
	fixYlinks();
	deSatTwoColors(backgroundTV,textTV);
	deSatColor(backgroundTV, backgroundTV); //backgroundTV has been modified by "deSatTwoColors".
	deSatColor(textTV, textTV); 
	deSatColor(linkTV, linkTV);
	deSatColor(vlinkTV, vlinkTV);
	parent.frames.tvColor.document.location='tvColor.html';
}

function cloneTheirColor(someObject, someObjectTV)
{
	someObjectTV.hex = someObject.hex;
	setPropertiesFromHex(someObjectTV);
}

function checkColor(name)
{
    if (name == "r" || name == "g" || name == "b") // is it an RGB?
		keepInLimits(name, 255);
    else if (name == "s" || name == "v")// is it S or B?
		keepInLimits(name, 100);
    else if (name == "h") // it must be hue
		keepInLimits(name, 360);
}

function checkForBrightWhites(someObjectTV)
{
    if (someObjectTV.red>230 && someObjectTV.green>230 && someObjectTV.blue > 230)
    {
        someObjectTV.hex =  "E5E5E5";
	setPropertiesFromHex(someObjectTV);
    }
}

function deSatColor(someObject, someObjectTV)
{
    if ((15 > someObject.hue || someObject.hue > 345) && someObject.saturation > 70)
        desaturateConstantY(someObject, someObjectTV, 69);
    else if (someObject.saturation > 82) //Note "dual gate technology"
		desaturateConstantY(someObject, someObjectTV, 80);
	else
		cloneTheirColor(someObject, someObjectTV);
}

function desaturateConstantY(someObject, someObjectTV, limit)
//Takes a color and returns the closest desaturated equivalent with idenitical "Y"
{
    ourR = someObject.red;  
    ourG = someObject.green;  
    ourB = someObject.blue;
    ourY = someObject.y; 

	while (returnSat(ourR,ourG,ourB) > limit) //As long as the color is saturated 
    {
	 // Rules:
	 // 1 - Add "2" to the miniumum RGB value (any 0 values will equal the minimum.
	 // 2 - If this changes Y more than 2 points, add or subtract across the board to restore it.
	 // 3 - Stay in loop until proper saturation is reached

		maxAndMin = bubbleSort(ourR,ourG,ourB);
		if (ourR == maxAndMin[0])
	    {
	        ourR +=2;
			if (ourG == maxAndMin[2])
		    	ourG -=2;
			else 
		    	ourB -=2;
	    }
		
		if (ourG == maxAndMin[0])
	    {
	        ourG +=2;
			if (ourB == maxAndMin[2])
		    	ourB -=2;
			else 
		    	ourR -=2;
	    }

		if (ourB == maxAndMin[0])
	    {
	        ourB +=2;
			if (ourR == maxAndMin[2])
		    	ourR -=2;
			else 
		    	ourG -=2;
	    }
		if (ourY +2 < returnY(ourR, ourG, ourB)) // Y now too large?
		{
	    	ourR -=2;
	    	ourG -=2;
	    	ourB -=2;
		}
		else if(ourY - 2 > returnY(ourR, ourG, ourB)) // Y now too small?
		{
	    	ourR +=2;
	    	ourG +=2;
	    	ourB +=2;
		} 
    }
    someObjectTV.red = ourR;  
    someObjectTV.green = ourG;  
    someObjectTV.blue = ourB; 
    RGBtoHSB(someObjectTV);
}

function deSatTwoColors(color1TV,color2TV)
{
    mod1Hue = 360 - color1TV.hue;
    mod2Hue = 360 - color2TV.hue;
    if (Math.abs(mod1Hue-mod2Hue) > 140 && parseInt(color1TV.saturation+color2TV.saturation) > 112) 
    {
		while (parseInt(color1TV.saturation+color2TV.saturation) > 125)
		{
	    	color1TV.saturation -=1;
	    	color2TV.saturation -=1;
		color1TV.brightness -=.5; //This will darken background so we don't end up with pastels.
		}
		HSBtoRGB(color1TV);
		HSBtoRGB(color2TV);
    }
}

function fixYlinks()
{
   if (Ydiff(backgroundTV, linkTV) <=74)// if the diff in Y for link is less than 74 
	if (linkTV.y >= backgroundTV.y) // if link has a bigger Y than background
	{
		if (roomToGrow(linkTV)) // Can we grow without going over 255?
			grow(linkTV, 75 - Ydiff(backgroundTV, linkTV),4);
		else // We're going to have to shrink
			shrink(linkTV, 75 - Ydiff(backgroundTV, linkTV),4);      
	}
	else // link has a smaller Y than background
	{
 	        if (willNotChangeTooMuch(linkTV, 75 - Ydiff(linkTV, backgroundTV))) //Can we shrink?
			shrink(linkTV, 75 - Ydiff(backgroundTV, linkTV),4);
		else // We're going to have to grow
			grow(linkTV, 75 - Ydiff(backgroundTV, linkTV),4);
	}
	RGBtoHSB(linkTV);

   if (Ydiff(backgroundTV, vlinkTV) <=74)// if the diff in Y for vlink is less than 74
	if (vlinkTV.y >= backgroundTV.y) // if vlink has a bigger Y than background
	{
		if (roomToGrow(vlinkTV)) // Can we grow without going over 255?
			grow(vlinkTV, 75 - Ydiff(backgroundTV, vlinkTV),4);  
		else // We're going to have to shrink
			shrink(vlinkTV, 75 - Ydiff(backgroundTV, vlinkTV),4); 
	}
	else // Vlink has a smaller Y than background
     {
         if (willNotChangeTooMuch(vlinkTV, 75 - Ydiff(vlinkTV, backgroundTV))) //Can we shrink?
			shrink(vlinkTV, 75 - Ydiff(backgroundTV, vlinkTV),4); 
         else // We're going to have to grow
			grow(vlinkTV, 75 - Ydiff(backgroundTV, vlinkTV),4);    
	}
	
	RGBtoHSB(vlinkTV);
}



function fixYtextBack()
{
	if (Ydiff(textTV,backgroundTV) <= 74)
    {
     // Here are the rules:
     // 1) Unless it changes them too much, modify all colors equally on text (people notice it less)
     // 2) Try to modify all colors equally on background
     // 3) Unless it changes them too much, modify hue on text
     // 4) Modify hue on background.
		if (textTV.y >= backgroundTV.y)//text has a bigger Y.
		{
			if (Ydiff(backgroundTV, textTV) <= 75)
			{
				grow(textTV, 75 - Ydiff(textTV, backgroundTV),1);
			}
			if (Ydiff(backgroundTV, textTV) <= 75)
			{
				shrink(backgroundTV, 75 - Ydiff(textTV, backgroundTV),1);
			}
			if (Ydiff(backgroundTV, textTV) <= 75)
			{
				grow(textTV, 75 - Ydiff(textTV, backgroundTV),4);
			}
			if (Ydiff(backgroundTV, textTV) <= 75)
			{
				shrink(backgroundTV, 75 - Ydiff(textTV, backgroundTV),4);
			}
		}

		else //Text has a smaller "Y"
		{
			if (Ydiff(backgroundTV, textTV) <= 75)
				shrink(textTV, 75 - Ydiff(textTV, backgroundTV),1);
			if (Ydiff(backgroundTV, textTV) <= 75)
				grow(backgroundTV, 75 - Ydiff(textTV, backgroundTV),1); 
			if (Ydiff(backgroundTV, textTV) <= 75)
				shrink(textTV, 75 - Ydiff(textTV, backgroundTV),4);
			if (Ydiff(backgroundTV, textTV) <= 75)
				grow(backgroundTV, 75 - Ydiff(textTV, backgroundTV),4);
		}
		RGBtoHSB(backgroundTV);
		RGBtoHSB(textTV);
    }
}



function grow(someObject,howMuch,tolerateMaxes)
{//Takes an object, how much to grow it, and whether to grow disproporionately, then increases the RGB values of the object accordingly
	var growY = 0;
	var maxedR = 0;
	var maxedG = 0;
	var maxedB = 0;
	while(growY <= howMuch && maxedR + maxedG + maxedB < tolerateMaxes && bubbleSort(someObject.red,someObject.green,someObject.blue)[0] < 231)
	{
		if (someObject.red <= 253)
		{
		    someObject.red  +=2;
			growY += .598;		
		}

		else
			maxedR = 1;
		if (someObject.green  <= 253)
		{
		    someObject.green +=2;
			growY += 1.174;
		}

		else
			maxedG = 1;

		if (someObject.blue <= 253)
		{
		    someObject.blue +=2;
			growY += .228;
		}

		else
			maxedB = 1;
	}
	setYfromRGB(someObject)// Set Y now so we can check it later.
}

function shrink(someObject,howMuch,tolerateMaxes)
{//Takes an object, how much to shrink it, and whether to shrink disproporionately, then decreases the RGB values of the object accordingly
	var shrinkY = 0;
	var maxedR = 0;
	var maxedG = 0;
	var maxedB = 0;
	while (shrinkY <= howMuch && maxedR + maxedG + maxedB < tolerateMaxes)
	{
		if (someObject.red >= 2)
		{
			someObject.red -=2;
			shrinkY += .598;
		}
		else
			maxedR = 1;

		if (someObject.green >= 2)
		{
		    someObject.green -=2;
			shrinkY += 1.174;
		}

		else
			maxedG = 1;

		if (someObject.blue >= 2)
		{
		    someObject.blue -=2;
			shrinkY += .228;
		}

		else
			maxedB = 1;
	}
	setYfromRGB(someObject)// Set Y now so we can check it later.
}

function willNotChangeTooMuch(someObject, howMuch)
{
	if (howMuch*2 < someObject.y)
		return true;
}

function roomToGrow(someObject)
{
 if (75 - Ydiff(backgroundTV, someObject) + someObject.y < 253)
 	return true;
}

function roomToShrink(someObject)
{
 if (someObject - (75 - Ydiff(backgroundTV, someObjectTV)) > 0)
 	return true;
}

function Ydiff(object1, object2)
{
    return Math.abs(object1.y - object2.y);
}

function keepInLimits(name, limit)
{
    if (parent.frames.selBoxes.document.ColorForm.elements[name].value =="")
        parent.frames.selBoxes.document.ColorForm.elements[name].value = 0;
    else if (parent.frames.selBoxes.document.ColorForm.elements[name].value >= 0 && parent.frames.selBoxes.document.ColorForm.elements[name].value <= limit)
		var foo = "bar";	
    else if (parent.frames.selBoxes.document.ColorForm.elements[name].value > limit)
		parent.frames.selBoxes.document.ColorForm.elements[name].value = limit;
    else if (parent.frames.selBoxes.document.ColorForm.elements[name].value < 0)
		parent.frames.selBoxes.document.ColorForm.elements[name].value = 0;
    else 
    {
	if (name == "r" || name == "g" || name == "b")
	    alert("Please make sure R, G, and B values range from 0 - 255");
    else if (name == "s" || name == "v")
        alert("Please make sure S, and V values range from 0 - 100");
    else if (name == "h")
        alert("Please make sure the value for Hue ranges from 0 - 359");
	parent.frames.selBoxes.document.ColorForm.elements[name].value = 0;
    }
}

function resetValues()
{
        background.hex = "000000";
        text.hex = "E6E6E6";
        link.hex = "3434FF";
        vlink.hex = "CC33FF";
	setPropertiesFromHex(background); 
	setPropertiesFromHex(text);
	setPropertiesFromHex(link);
	setPropertiesFromHex(vlink);
	cloneTheirColor(background, backgroundTV);
	cloneTheirColor(text, textTV);
	cloneTheirColor(link, linkTV);
	cloneTheirColor(vlink, vlinkTV);

        parent.frames.theirColor.document.location='theirColor.html';
	parent.frames.tvColor.document.location = 'tvColor.html';
	populateRGB(getChoice());
}

function convertToHex(num) //Bill Dortch is the man.
{
var chars = "0123456789ABCDEF";
  return chars.charAt((num>>4)&0xf)+chars.charAt(num&0xf);
}

function returnSat(red,green,blue)
{
    values = bubbleSort(red,green,blue);
    if (values[2] == 0)
		return 0;
    else
    {
    	Bri = values[2]/255;
    	return 100*(Bri - (values[0] / 255.0)/Bri);
    }
}

function HSBtoRGB(someObject)
{
    Hue = someObject.hue;
    Sat = someObject.saturation/100;
    Bri = someObject.brightness/100;

    var exit = "false";
    if(Sat == 0 )
    {
        red =  Bri;
        green =  Bri;
        blue =  Bri;
        var exit="true";
    }

    if (exit != "true")
    {
        Hue = Hue/60;
        var i = Math.floor(Hue);
        var f =  Hue -  i;
        var p =  Bri * (1.0 -  Sat );
        var q =  Bri * (1.0 -  Sat *  f );
        var t =  Bri * (1.0 -  Sat * ( 1.0 -  f ) );
        if (i ==0)
        {
            red =  Bri;
            green =  t;
            blue =  p;
        }

        else if ( i==1)
        {
            red =  q;
            green =  Bri;
            blue =  p;
        }

        else if ( i==2)
        {
            red =  p;
            green =  Bri;
            blue =  t;
        }

        else if ( i==3)
        {
	    	red =  p;
        	green =  q;
			blue =  Bri;
        }

        else if( i==4)
        {
            red =  t;
            green =   p;
            blue =  Bri;
        }

        else
        {
            red =  Bri;
            green =  p;
            blue =  q;
        }
    }
someObject.red = red*255;
someObject.green = green*255;
someObject.blue = blue*255;
someObject.hex = convertToHex(Math.round(someObject.red))+convertToHex(Math.round(someObject.green))+convertToHex(Math.round(someObject.blue));
setYfromRGB(someObject);
}

function RGBtoHSB(someObject)

//takes an object and updates HSB, y, and Hex based on current RGB
{
   red = someObject.red;
   green = someObject.green;
   blue = someObject.blue;
   colors = bubbleSort(red, green, blue);

   var domainBase, domainOffset;

    if (colors[2] == 0)
    {
	Bri = 0;
	Sat = 0;
    }

    else
    {
	Bri = colors[2]/255;
	Sat = (Bri - (colors[0] / 255.0))/Bri;
    }

    var oneSixth = 1.0/ 6.0;
    domainOffset = ( colors[1] -  colors[0]) /(colors[2] -  colors[0]) / 6.0;

	if (colors[2]==colors[0])
		Hue = 0;
	else
	{
		if (red == colors[2])
        {
            if ( colors[1] ==  green)
                domainBase = 0 / 6.0;
            else
            {
                domainBase = 5 / 6.0;
                domainOffset =  oneSixth -  domainOffset;
            }
        }

        else if ( green ==  colors[2])
        {
            if ( colors[1] ==  blue)
                domainBase = 2 / 6.0;
            else
            {
                domainBase = 1 / 6.0;
                domainOffset =  oneSixth -  domainOffset;
            }
       }

  	else
        {
            if ( colors[1] ==  red)
                domainBase = 4 / 6.0;
            else
            {
                domainBase = 3 / 6.0;
                domainOffset =  oneSixth -  domainOffset;
            }
        }
        Hue =  domainBase +  domainOffset;
    }
someObject.hue = Math.round(Hue*360);
someObject.saturation = Math.round(100*Sat);
someObject.brightness = Math.round(100*Bri);
someObject.hex =convertToHex(Math.round(someObject.red))+convertToHex(Math.round(someObject.green))+convertToHex(Math.round(someObject.blue));
setYfromRGB(someObject);

} 



function checkTheirHex(theirHexValue)
{
    if (theirHexValue.length != 6)
    { 
	alert("That entry is not a valid hex triplet. Resetting to '000000'.");
	parent.frameparent.frames.selBoxes.document.ColorForm.theirHex.value = "000000";
	return;
    }

    for (i=0;i<=6;i++)
    {
	charo= theirHexValue.charAt(i);
    	if (isDigit(charo) || isGoodLetter(charo))
	    return;
        else
        {
	    alert("That entry is not a valid hex triplet. Resetting to '000000'");
	    parent.frames.selBoxes.document.ColorForm.theirHex.value = "000000";
		return;
        }
    }
}

function isDigit(d)
{
    return (d >= "0" && d <= "9")
}

function isGoodLetter(l)
{
    return ((l >= "a" && l <= "f") || (l >= "A" && l <= "F"));
}

function getChoice() //Returns the text in the pull-down menu
{
    for (var i = 0; i < parent.frames.selBoxes.document.ColorForm.optionList.length; i++) 
    {
	if (parent.frames.selBoxes.document.ColorForm.optionList.options[i].selected == true) 
	{
	    if (parent.frames.selBoxes.document.ColorForm.optionList.options[i].text == "Background")
			return background;
		else if (parent.frames.selBoxes.document.ColorForm.optionList.options[i].text == "Text")
			return text;
		else if (parent.frames.selBoxes.document.ColorForm.optionList.options[i].text == "Link")
			return link;
		else if (parent.frames.selBoxes.document.ColorForm.optionList.options[i].text == "Visited Link")
			return vlink;
	}	
    }
    return null;
}

function getChoiceTV() //Returns the TV alternative in the pull-down menu
{
    for (var i = 0; i < parent.frames.selBoxes.document.ColorForm.optionList.length; i++) 
    {
	if (parent.frames.selBoxes.document.ColorForm.optionList.options[i].selected == true) 
		{
	    if (parent.frames.selBoxes.document.ColorForm.optionList.options[i].text == "Background")
			return backgroundTV;
		else if (parent.frames.selBoxes.document.ColorForm.optionList.options[i].text == "Text")
			return textTV;
		else if (parent.frames.selBoxes.document.ColorForm.optionList.options[i].text == "Link")
			return linkTV;
		else if (parent.frames.selBoxes.document.ColorForm.optionList.options[i].text == "Visited Link")
			return vlinkTV;
		}	
    }
    return null;
}

function bubbleSort(one,two,three)

{
    var arrayName = new Array(one,two,three);
     for (var i=0; i<2; i++)
         for (var j=i+1; j<3; j++)
             if (arrayName[j] < arrayName[i]) {
                 var dummy = arrayName[i];
                 arrayName[i] = arrayName[j];
                 arrayName[j] = dummy;
             }
return arrayName;
}