/**
 * jQuery Plugin colorBlend v1.0
 * Requires jQuery 1.2.1 (Not tested with earlier versions).
 * Based on the Fade plugin http://plugins.jquery.com/project/fade
 * Code losely based on the Cycle plugin http://plugins.jquery.com/project/cycle It was a great resource in creating this one) 
 * Copyright (c) 2007 Aaron E. [jquery at happinessinmycheeks dot com] 
 * 
 * @param: Object Array. Arguments need to be in object notation.
 * returns: jQuery.
 * options:	
 *		param:		What css color option you wish to fade. 
 *					Such as "background-color", "color", "boarder-color", "scrollbar-face-color" (I.E. Only) Etc.
 *					(default: "background-color).
 *		fps:		Frames per second (default: 30).
 *		cycles:		How many times you want the object to fade. 0 = Infinite. (default: 0).
 *		random:		Will transition from a random color to a random color. (default: false).
 *					Note: Will change isFade to false.
 *		isFade:		Will fade from to and back to the original color. (default: true).
 *					Note: Not changeable to true if random is set to true.
 *		fromColor:	Starting color. accepts RGB, Hex, Name values. (default: #000000).
 *					Will be overwritten if random is set to true. Also accepts "random" as an option.
 *		toColor:	Ending color. Same as above (default: #FFFFFF).
 *
 * Examples: 
 *		$("body").colorBlend([{fromColor:"black", toColor:"white", param:"color"}]);
 *		var myColors = [
 *			{param:'color', fromColor:"white", toColor:"black"},
 *			{param:'background-color', random: true},
 *			{param:'border-left-color', fromColor:"random", toColor:"black"},
 *			{param:'border-right-color', fromColor:"white", toColor:"black"},
 *			{param:'border-top-color', fromColor:"white", toColor:"black"},
 *			{param:'border-bottom-color', fromColor:"white", toColor:"tomato"}
 *		];
 *		$("tr").colorBlend(myColors);
 *
 *
 * Notes: If used on a lot of objects it can cause major lag. 
 */
(function($) {
	var ver = '1.0';
	var thisObj = [];
	$.fn.colorBlend = function(opts) {
		return this.each(function() {
			var $cont = $(this);
			var domObj = $(this).get(0);
			domObj.elmId = [];
			
			$.each(opts, function(i) {
				var defOps = {
					aniArray: [],
					lastPos: 0,
					pos: 0,
					currentCycle : 0,
					direction: 1,
					frames: 0,
					delay: 0,
					fromRand: false,
					toRand: false,
					animating: false
				};

				opts[i] = $.extend({}, $.fn.colorBlend.defaults, opts[i]);

				if(udf(domObj.elmId[i])) {
					domObj.elmId[i] = rndId();
				}

				thisObj[domObj.elmId[i]] = defOps;

				var inOps = thisObj[domObj.elmId[i]];
				var usOps = opts[i];
				
				if(!inOps.animating) {
					if(usOps.fromColor.toLowerCase() == "random" || inOps.fromRand) {
						usOps.fromColor = rndColor();
						inOps.fromRand = true;
					}
					
					if(usOps.toColor.toLowerCase() == "random" || inOps.toRand) {
						usOps.toColor = rndColor();
						inOps.toRand = true;
					}
					
					$cont.css(usOps.param, usOps.fromColor);

					inOps.currentCycle = usOps.cycles > 0 ? usOps.cycles : 0;
					inOps.frames = Math.floor(usOps.fps * (usOps.duration / 1000));
					inOps.delay = Math.floor(usOps.duration / inOps.frames);

					if(usOps.random) {
						usOps.isFade = false;
						usOps.fromColor = rndColor();
						usOps.toColor = rndColor();
					}
					
					if(usOps.isFade) {
						inOps.currentCycle = inOps.currentCycle * 2;
						inOps.delay = Math.floor(inOps.delay / 2);
						inOps.frames = Math.floor(inOps.frames / 2);
					}

					inOps.aniArray = buildAnimation(usOps.fromColor, usOps.toColor, inOps);
					inOps.lastPos = inOps.aniArray.length;

					go($cont, usOps, inOps);
				}
			});
		});
	};

	$.fn.colorBlend.defaults = {
		fps:				30,
		duration:			1000,
		param:				"background-color",
		cycles:				0,
		random:				false,
		isFade:				true,
		fromColor:			"#000000",
		toColor:			"#FFFFFF"
	};

	function go(elm, opts, inOps) {
		var sendStop = false;
		inOps.animating = true;
		elm.css(opts.param, inOps.aniArray[inOps.pos]);
		
		inOps.pos += inOps.direction; 

		if(inOps.pos < 0 || inOps.pos >= inOps.aniArray.length) {
			inOps.currentCycle -= inOps.currentCycle != 0 ? 1 : 0;
			inOps.direction = inOps.direction * -1;
			inOps.pos += inOps.direction;

			if(opts.random) {
				opts.fromColor = opts.toColor;
				opts.toColor = rndColor();
				inOps.aniArray = buildAnimation(opts.fromColor, opts.toColor, inOps);
			}

			if(!opts.isFade) {
				inOps.direction = 1;
				inOps.pos = 0;
			}
			
			if(inOps.currentCycle == 0 && opts.cycles > 0) {
				sendStop = true;
			}
		}

		if(!sendStop) {
			setTimeout(function(){go(elm, opts, inOps);}, inOps.delay);
		} else {
			inOps.animating = false;
		}
	}

	function buildAnimation(startColor, endColor, inOps) {
		startColor = (startColor.toLowerCase() == 'transparent' || startColor.toLowerCase() == "random") ? rndColor() : startColor;
		endColor = (endColor.toLowerCase() == 'transparent' || endColor.toLowerCase() == "random") ? rndColor() : endColor;
		
		startColor = toHexColor(startColor);
		endColor = toHexColor(endColor);
		var frames = inOps.frames;
		var frame = 0;
		var fc = ColorHexToDec(startColor).split(', '); 
		var tc = ColorHexToDec(endColor).split(', ');
		var r,g,b,h;
		var res = [];
		
		while(frame < frames) {
			r = Math.floor(fc[0] * ((frames-frame)/frames) + tc[0] * (frame/frames));
			g = Math.floor(fc[1] * ((frames-frame)/frames) + tc[1] * (frame/frames));
			b = Math.floor(fc[2] * ((frames-frame)/frames) + tc[2] * (frame/frames));
			h = ColorDecToHex(r, g, b);
			res[res.length] = h;
			frame++;
		}

		if(h != endColor) {
			res[res.length] = endColor;
		}
		
		return res;
	}

	function getHexColorByName(colorName) {
		return allColorsByName()[colorName.toLowerCase()];
	}

	function allColorsByName() {
		var colors = [];
		colors["aliceblue"] = "F0F8FF";
		colors["antiquewhite"] = "FAEBD7";
		colors["aqua"] = "00FFFF";
		colors["aquamarine"] = "7FFFD4";
		colors["azure"] = "F0FFFF";
		colors["beige"] = "F5F5DC";
		colors["bisque"] = "FFE4C4";
		colors["black"] = "000000";
		colors["blanchedalmond"] = "FFEBCD";
		colors["blue"] = "0000FF";
		colors["blueviolet"] = "8A2BE2";
		colors["brown"] = "A52A2A";
		colors["burlywood"] = "DEB887";
		colors["cadetblue"] = "5F9EA0";
		colors["chartreuse"] = "7FFF00";
		colors["chocolate"] = "D2691E";
		colors["coral"] = "FF7F50";
		colors["cornflowerblue"] = "6495ED";
		colors["cornsilk"] = "FFF8DC";
		colors["crimson"] = "DC143C";
		colors["cyan"] = "00FFFF";
		colors["darkblue"] = "00008B";
		colors["darkcyan"] = "008B8B";
		colors["darkgoldenrod"] = "B8860B";
		colors["darkgray"] = "A9A9A9";
		colors["darkgreen"] = "006400";
		colors["darkkhaki"] = "BDB76B";
		colors["darkmagenta"] = "8B008B";
		colors["darkolivegreen"] = "556B2F";
		colors["darkorange"] = "FF8C00";
		colors["darkorchid"] = "9932CC";
		colors["darkred"] = "8B0000";
		colors["darksalmon"] = "E9967A";
		colors["darkseagreen"] = "8FBC8F";
		colors["darkslateblue"] = "483D8B";
		colors["darkslategray"] = "2F4F4F";
		colors["darkturquoise"] = "00CED1";
		colors["darkviolet"] = "9400D3";
		colors["deeppink"] = "FF1493";
		colors["deepskyblue"] = "00BFFF";
		colors["dimgray"] = "696969";
		colors["dodgerblue"] = "1E90FF";
		colors["firebrick"] = "B22222";
		colors["floralwhite"] = "FFFAF0";
		colors["forestgreen"] = "228B22";
		colors["fuchsia"] = "FF00FF";
		colors["gainsboro"] = "DCDCDC";
		colors["ghostwhite"] = "F8F8FF";
		colors["gold"] = "FFD700";
		colors["goldenrod"] = "DAA520";
		colors["gray"] = "808080";
		colors["green"] = "008000";
		colors["greenyellow"] = "ADFF2F";
		colors["honeydew"] = "F0FFF0";
		colors["hotpink"] = "FF69B4";
		colors["indianred"] = "CD5C5C";
		colors["indigo"] = "4B0082";
		colors["ivory"] = "FFFFF0";
		colors["khaki"] = "F0E68C";
		colors["lavender"] = "E6E6FA";
		colors["lavenderblush"] = "FFF0F5";
		colors["lawngreen"] = "7CFC00";
		colors["lemonchiffon"] = "FFFACD";
		colors["lightblue"] = "ADD8E6";
		colors["lightcoral"] = "F08080";
		colors["lightcyan"] = "E0FFFF";
		colors["lightgoldenrodyellow"] = "FAFAD2";
		colors["lightgreen"] = "90EE90";
		colors["lightgrey"] = "D3D3D3";
		colors["lightpink"] = "FFB6C1";
		colors["lightsalmon"] = "FFA07A";
		colors["lightseagreen"] = "20B2AA";
		colors["lightskyblue"] = "87CEFA";
		colors["lightslategray"] = "778899";
		colors["lightsteelblue"] = "B0C4DE";
		colors["lightyellow"] = "FFFFE0";
		colors["lime"] = "00FF00";
		colors["limegreen"] = "32CD32";
		colors["linen"] = "FAF0E6";
		colors["magenta"] = "FF00FF";
		colors["maroon"] = "800000";
		colors["mediumaquamarine"] = "66CDAA";
		colors["mediumblue"] = "0000CD";
		colors["mediumorchid"] = "BA55D3";
		colors["mediumpurple"] = "9370DB";
		colors["mediumseagreen"] = "3CB371";
		colors["mediumslateblue"] = "7B68EE";
		colors["mediumspringgreen"] = "00FA9A";
		colors["mediumturquoise"] = "48D1CC";
		colors["mediumvioletred"] = "C71585";
		colors["midnightblue"] = "191970";
		colors["mintcream"] = "F5FFFA";
		colors["mistyrose"] = "FFE4E1";
		colors["moccasin"] = "FFE4B5";
		colors["navajowhite"] = "FFDEAD";
		colors["navy"] = "000080";
		colors["oldlace"] = "FDF5E6";
		colors["olive"] = "808000";
		colors["olivedrab"] = "6B8E23";
		colors["orange"] = "FFA500";
		colors["orangered"] = "FF4500";
		colors["orchid"] = "DA70D6";
		colors["palegoldenrod"] = "EEE8AA";
		colors["palegreen"] = "98FB98";
		colors["paleturquoise"] = "AFEEEE";
		colors["palevioletred"] = "DB7093";
		colors["papayawhip"] = "FFEFD5";
		colors["peachpuff"] = "FFDAB9";
		colors["peru"] = "CD853F";
		colors["pink"] = "FFC0CB";
		colors["plum"] = "DDA0DD";
		colors["powderblue"] = "B0E0E6";
		colors["purple"] = "800080";
		colors["red"] = "FF0000";
		colors["rosybrown"] = "BC8F8F";
		colors["royalblue"] = "4169E1";
		colors["saddlebrown"] = "8B4513";
		colors["salmon"] = "FA8072";
		colors["sandybrown"] = "F4A460";
		colors["seagreen"] = "2E8B57";
		colors["seashell"] = "FFF5EE";
		colors["sienna"] = "A0522D";
		colors["silver"] = "C0C0C0";
		colors["skyblue"] = "87CEEB";
		colors["slateblue"] = "6A5ACD";
		colors["slategray"] = "708090";
		colors["snow"] = "FFFAFA";
		colors["springgreen"] = "00FF7F";
		colors["steelblue"] = "4682B4";
		colors["tan"] = "D2B48C";
		colors["teal"] = "008080";
		colors["thistle"] = "D8BFD8";
		colors["tomato"] = "FF6347";
		colors["turquoise"] = "40E0D0";
		colors["violet"] = "EE82EE";
		colors["wheat"] = "F5DEB3";
		colors["white"] = "FFFFFF";
		colors["whitesmoke"] = "F5F5F5";
		colors["yellow"] = "FFFF00";
		colors["yellowgreen"] = "9ACD32";
		return colors;
	}

	function ColorDecToHex(r,g,b) {
		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 "#" + r + g + b;
	}

	function ColorHexToDec(value) {
		var res = [];
		value = value.replace("#", "");
		for(var i = 0;i < 3;i++) {
			res[res.length] = parseInt(value.substr(i * 2, 2), 16);
		}
		return res.join(', ');
	}

	function toHexColor(value) {
		if(value.indexOf("rgb(") > -1) {
			value = value.replace("rgb(","").replace(")", "");
			value = eval('ColorDecToHex(' + value + ')'); 
		} else {
			var colName = getHexColorByName(value);
			value = !udf(colName) ? colName : value;
		}
		
		value = value.replace("#", "");
		return "#" + value.toUpperCase();
	}

	function rndColor() {
		var res = [];
		var cm;
		for(var i = 0;i < 3;i++) {
			cm = randRange(0, 255).toString(16); 
			if (cm.length == 1) cm = '0' + cm;
			res[res.length] = cm;
		}
		return "#" + res.join('');
	}

	function randRange(lowVal, highVal) {
		 return Math.floor(Math.random()*(highVal-lowVal+1))+lowVal;
	}

	function rndId() {
		var result = [];
		for(var i = 0;i < 10;i++) {
			result[result.length] = randRange(0, 9);
		}
		return result.join('');
	}

	function udf(val) {
		return typeof(val) == 'undefined' ? true : false;
	}

})(jQuery);

