//
// An element animator.
//
// Nat Friedman (nat@novell.com)
//
// To fade in the element "elt" over two seconds:
//     Animator.animate (elt, 2000, [{param: "opacity", from: 0.0, to: 1.0}]);
//
// To fade out over 150 milliseconds:
//     Animator.animate (elt, 150, [{param: "opacity", from: 1.0, to: 0.0}]);
//
// To slide from left to right and then popup an alert:
//     elt.onAnimationFinished = function () { alert ("Done animating!"); };
//     Animator.animate (elt, 1000, [{param: "left", from: 0, to: 500}]);
//
// To shift to red over a second:
//     Animator.animate (elt, 1000, [{param: "color", to: "#ff0000"}]);
//
// To shift from blue to green and fade out:
//     Animator.animate (elt, 1000, [{param: "color", from: "#0000ff", to: "#00ff00"}, {param: "opacity", from: 1.0, to: 0.0}]);
//
// To shift from red to blue and fade in and slide from right to left:
//     Animator.animate (elt, 3500, [{param: "color", from: "#ff0000", to: "#0000ff"}, {param: "opacity", from: 0.0, to: 1.0}, {param: "right", from: 600, to: 0}]);
//

var Animator = {

	fps: 30,

	animate : function (elt, duration, animList) {

		if (elt.animTimerId)
			clearInterval (elt.animTimerId);

		elt.animOps = new Array ();

		elt.animFrames = Math.round (this.fps * (duration / 1000));
		elt.animInterval = 1000 / this.fps;

		for (var i = 0; i < animList.length; i ++) {
			var op = {};

			op.param = animList [i].param;

			if (op.param == "color") {

				if (animList [i].from == null)
					animList [i].from = this.getColor (elt);
				
				op.redFrom   = parseInt (animList [i].from.substr(1,2),16);
				op.greenFrom = parseInt (animList [i].from.substr(3,2),16);
				op.blueFrom  = parseInt (animList [i].from.substr(5,2),16);
				op.redTo     = parseInt (animList [i].to.substr(1,2),16);
				op.greenTo   = parseInt (animList [i].to.substr(3,2),16);
				op.blueTo    = parseInt (animList [i].to.substr(5,2),16);
			} else {
				op.from = animList [i].from;
				op.to = animList [i].to;
			}

			elt.animOps [elt.animOps.length] = op;
		}

		elt.animFrame = 0;

		elt.animTimerId = setInterval ("Animator.step ('" + elt.id + "')", elt.animInterval);
	},

	step : function (id) {
		var elt = document.getElementById (id);

		var completed = elt.animFrame / elt.animFrames;
		var inverseCompleted = (elt.animFrames - elt.animFrame) / elt.animFrames;

		for (var i = 0; i < elt.animOps.length; i ++) {
			var op = elt.animOps [i];

			if (op.param == "color") {
				var r = Math.floor (op.redFrom * inverseCompleted + op.redTo * completed);
				var g = Math.floor (op.greenFrom * inverseCompleted + op.greenTo * completed);
				var b = Math.floor (op.blueFrom * inverseCompleted + op.blueTo * completed);
				var h = this.makeHex (r, g, b);

//				Debug.print ("From: " + this.makeHex (op.redFrom, op.greenFrom, op.blueFrom) + " to: " +
//					     this.makeHex (op.redTo, op.greenTo, op.blueTo) + " step: " + h);

				this.setColor (id, h);
			} else {
				elt.style [op.param] = Number (op.from) * inverseCompleted + Number (op.to) * completed;
//				Debug.print ("From: " + op.from);
//				Debug.print ("elt.style [" + op.param + "] = " + ((Number (op.from) * inverseCompleted) + (Number (op.to) * completed)) + ";");
//				Debug.print ("Frame: " + elt.animFrame + " Frames: " + elt.animFrames);
			}
		}

		elt.animFrame ++;

		if (elt.animFrame > elt.animFrames) {

			clearInterval (elt.animTimerId);
			
			elt.animTimerId = null;

			if (elt.onAnimFinished)
				elt.onAnimFinished (elt.onAnimFinishedClosure);
		}
	},

	makeHex : function (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;
	},

	setColor : function (id, color) {
		o = document.getElementById (id);
		o.style.backgroundColor = color;
	},

	getColor : function (elt) {
		var c;

		while (elt) {
			if (window.getComputedStyle)
				c = window.getComputedStyle (elt, null).getPropertyValue ("background-color");
			if (elt.currentStyle)
				c = elt.currentStyle.backgroundColor;

			if ((c != "" && c != "transparent") || elt.tagName == "BODY")
				break;

			elt = elt.parentNode;
		}

		if (c == undefined || c == "" || c == "transparent")
			c = "#FFFFFF";
			
		var rgb = c.match (/rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/);

		if (rgb) c = this.makeHex (parseInt (rgb[1]), parseInt (rgb[2]), parseInt (rgb[3]));

		return c;
	}
};
