// js animation library
//
// (c) mfx@dasburo.com
//
// es gibt eine "animation"-Klasse, die die aktuelle position und das aktuelle "target"
// abspeichert. das target wird durch eine methode gegeben, die die aktuellen absoluten
// koordinaten berechnet. wir arbeiten nicht mit vorberechneten pfaden, sondern dynamisch.
//
// es gibt einen globalen time-advancer, der in jedem schritt die jeweils aktiven
// animationen animiert, u.U. mit einer Null-Animation.
//

var NS4 = (document.layers) ? 1 : 0;
var IE4 = (document.all) ? 1 : 0;

function prot(x){
//	java.lang.System.out.println(x);
}

function set_x(x) {
	this.element.left = Math.floor(x);
}
function set_y(y) {
	this.element.top = Math.floor(y);
}
function set_xy(x,y) {
	this.element.left = Math.floor(x);
	this.element.top = Math.floor(y);
}
function get_x() {
	return (NS4) ? this.element.left : this.element.pixelLeft;
}
function get_y() {
	return (NS4) ? this.element.top : this.element.pixelTop;
}
function show() {
	this.element.visibility = (NS4) ? "show" : "visible";
}
function hide() {
	this.element.visibility = (NS4) ? "hide" : "hidden";
}

w_animations = new Array();		// all currently existing animation objects
w_delay      = 100;				// target speed: 10 frames/sec
w_timer      = null;
w_last       = 0;

w_animation_age = 0;			// 0=forever

function register_animation(a){
	var w_size = w_animations.length;
	w_animations[w_size++] = a;
}
function next_step () {
	prot("next_step");
	if(w_animation_age && w_animation_age-- == 1){
		alert("stopping this madness");
		stop_world();
		return;
	}
	var now = (new Date()).getTime();
	var delta= now - w_last;
	w_last = now;
	var w_size = w_animations.length;
	for(var i = 0; i< w_size; i++){
		var a = w_animations[i];
		if(a && a.action && a.animate){
			a.animate(delta);
		}
	}
	w_timer = window.setTimeout("next_step()", w_delay);
}
function start_world() {
	prot("start_world");
	w_last = (new Date()).getTime();
	clearInterval(w_timer);
	next_step();
}
function stop_world() {
	prot("stop_world");
	clearInterval(w_timer);
}
function set_world_speed(speed) {
	if(speed > 25) speed = 25;
	if(speed <= 0) {
		stop_world();
		return;
	}
	w_delay = 1000 / speed;
}
function animate (delta) {
	prot("  animate("+delta+")");
	this.done += delta;
	if(this.done < this.todo){
		this.action(this.done / this.todo);
		return;
	}
	if(this.action){
		//alert("typeof action=" + typeof(this.action));
		this.action(1.0);
	}
	if(this.next){
		prot("  eval next: "+this.next);
		this.done = 0;
		eval(this.next);
	} else {
		prot("  no eval next");
		this.action = null;
	}
}

function animation(id) {
	this.element = (NS4) ? document[id] : document.all[id].style;

	if(! this.element) {
		alert("element not found: id");
		return;
	}
	this.animate= animate;
	this.action = null;
	this.show   = show;
	this.hide   = hide;
	this.get_x  = get_x;
	this.get_y  = get_y;
	this.set_x  = set_x;
	this.set_x  = set_y;
	this.set_xy = set_xy;
	this.choose_target = choose_target;
	this.aim_follow = aim_follow;
	this.move = move;

	register_animation(this);
}

function move_to(obj, x0,y0, x1, y1, ratio) {
	var tx = (x1-x0) * ratio + x0;
	var ty = (y1-y0) * ratio + y0;
	obj.set_xy(tx,ty);
}

function choose_target() {
	this.target_x = Math.random() * (this.x1-this.x0) + this.x0;
	this.target_y = Math.random() * (this.y1-this.y0) + this.y0;
	this.start_x = this.get_x();
	this.start_y = this.get_y();
	prot("chose target " + this.target_x + ", "+ this.target_y);
}

function aim_follow(){
	var best_dist = -1;
	if(this.follow){
		var sz = this.follow.length;
		for(var i=0;i<sz;i++){
			var f = this.follow[i];
			if(f){
				var x = f.get_x();
				var y = f.get_y();
				var d = x*x + y*y;
				var fluffyness = this.speed / 50;
				var r = Math.random() < fluffyness;
				var choose_this = (d < best_dist);
				if(r) choose_this = !choose_this;
				if(best_dist == -1 || choose_this){
					best_dist = d;
					this.target_x = x;
					this.target_y = y;
				}
			}
		}
	}
	this.start_x = this.get_x();
	this.start_y = this.get_y();	

	// nun gilt es, die geschwindigkeit zu normieren und die
	// zeit anzupassen

	var dx = this.target_x - this.start_x;
	var dy = this.target_y - this.start_y;
	var len = Math.sqrt(best_dist);
	if(len > 1){
		dx = dx / len;
		dy = dy / len;
		// (dx, dy) bilden jetzt einen einheitsvektor

		dx *= this.speed;
		dy *= this.speed;

		this.target_x = this.start_x + dx;
		this.target_y = this.start_y + dy;
	}
	this.done = 0;
	this.todo = 100; // nach jedem schritt neuberechnung
}

function move(ratio) {
	prot("move " + ratio);

	move_to(this, this.start_x, this.start_y, this.target_x, this.target_y, ratio);
}

function setup_random(anim, x0,y0,x1,y1, delay){
	anim.x0 = x0;
	anim.y0 = y0;
	anim.x1 = x1;
	anim.y1 = y1;
	anim.todo = delay;
	anim.done = 0;
	anim.next = "this.choose_target()";
	anim.action = move;
	anim.choose_target();
}

function setup_follow(anim, follow, speed) {
	anim.todo = 1000;
	anim.done = 0;
	anim.speed = speed;
	anim.follow = new Array();
	anim.follow[0] = follow;
	anim.next = "this.aim_follow()";
	anim.action = move;
	anim.aim_follow();
}

function setup_follow_array(anim, follow, speed) {
	anim.todo = 1000;
	anim.done = 0;
	anim.speed = speed;
	anim.follow = follow;
	anim.next = "this.aim_follow()";
	anim.action = move;
	anim.aim_follow();
}
