/*
 * Transformer 0.1  -  * (c) 2003 by Navid Zamani
 *
 * Current Bugs:
 * - Under specific conditions a double-speed play can be triggered
 * - A framerate below 25 does not work :-(
 * - deltaT wird nicht auf nachfolgende flames vererbt und kann negative delay-werte erzeugen!
 */

function Transformer(targetId,path) {
	// unique id to separate animations
	this.id = targetId + ((new Date()).valueOf()) + Math.round(Math.random()*0x100);
	// the element to animate
	this.target = document.getElementById(targetId);
	// how to animate
	this.animationPath = path;
	// animation status variableds
	this.playID = null
	this.begin = 0; // animation start limit (step.morph)
	this.end = this.animationPath.length-1; // animation stop limit (step.morph)
	this.pos = 0; // step on animationPath + percent of morph from stepPos to stepPos+1
	this.deltaMorph = 0; // nr of frames for active step.
	this.delay = Math.round(1000/this.animationPath.fps); // animation speed delay
	this.lastStepPos = -1;
	
	// control methods
	// start animation from current position
	this.play = function() {
		if (!this.playID) {
			if (("debug" in document) && (document.debug = true)) alert("Starting play at postition: "+this.pos);
			this.playID = setInterval("document.animations['"+this.id+"'].tick()",this.delay);
		}
	}
	// stop animation
	this.stop = function() {
		if (this.playID != null) {
			clearInterval(this.playID); this.playID = null;
			if (("debug" in document) && (document.debug = true)) alert("Stopping play at postition: "+this.pos);
		}
	}
	// jump to step,morph
	this.jump = function(to) {
		this.pos = to;
		if (this.playID == null) this.playID = setInterval("document.animations['"+this.id+"'].tick()",this.delay);
		if (("debug" in document) && (document.debug = true)) alert("Jumping to: "+this.pos);
	}
	// limit animation from start to stop
	this.limit = function(begin,end) {
		this.begin = begin;
		this.end = end;
		if (("debug" in document) && (document.debug = true)) alert("Limiting to:\n"+this.begin+" - "+this.end);
		if (this.begin > this.pos) this.jump(this.begin);
		if (this.end < this.pos) this.jump(this.end);
		else this.stop();
	}
	
	// internal animation routine
	this.tick = function() {
		if (this.playID != null) {
			var stepPos = Math.floor(this.pos); var morphPos = (this.pos % 1); // splitted position values
			var from = this.animationPath[stepPos].style; // start and...
			var to = this.animationPath[stepPos+1].style; // ...end style
			var morphed = this.target.style; // calculated target style
			// Get the number of frames wich can be rendered in "duration" ms, when
			// every frame takes "delay" ms. Then get the percentage of morph for one frame.
			// (floating-point value required!!)
			this.deltaMorph = 1/(this.animationPath[stepPos].duration/this.delay);
			var fromS = null; var toS = null; var unitS = null; // loop state variables
			for (var s in to) { // for every style property (defined in "to")
				// take from value, to value,  and the unit. Then...
				fromS = parseInt(from[s]); toS = parseInt(to[s]); unitS = to[s].match(/[0-9]+([^0-9]+)/)[1];
				// Take the difference between fromS and toS. Take morphPos percent of it. Add this to fromS. And you'll get the morphedS!
				morphed[s] = (fromS + ((toS-fromS) * morphPos)) + unitS;
			}
			if (("debug" in document) && (document.debug = true)) window.status = "Animating "+this.target.id+" @ Pos: "+this.pos+" / Step-Duration: "+(this.animationPath[stepPos].duration/1000)+" s / Delay:"+this.delay+" ms / deltaMorph: "+this.deltaMorph;
			// avance one detaMorph
			this.pos += this.deltaMorph; // morph advancer (unexact!!)
			// if end reached go to (begin+remainder)
			if (this.pos > this.end) {
				if (this.animationPath.loop) {
					this.pos = this.begin + (this.pos - this.end);
					if (this.animationPath.loop !== true) this.animationPath.loop--;
				} else
					this.stop();
			} else {
				stepPos = Math.floor(this.pos); // for event calcs
				if (("callback" in this.animationPath[stepPos]) && (this.animationPath[stepPos].callback != undefined) && (this.lastStepPos != stepPos))
					this.animationPath[stepPos].callback(this.target,stepPos);
				this.lastStepPos = stepPos;
			}
			
		}
	}

	// register for animation
	if (!("animations" in document)) document.animations = []; //init if first animation
	document.animations[this.id] = this; // add self
	if (("debug" in document) && (document.debug = true)) alert("Created a Transformer!\n Id: "+this.id+"\nTarget: "+this.target.id);
}
	
