// -------------------------------------------------------------
// This defines an object that does animation.
//
// Usage:
//   var a = new Animation("dataimg", "a", 
//                         "imgsmall/loading_image_animation.jpg");
//                   // First argument is name of image to be animated. Second
//                   // is the name of the global variable that contains this
//                   // object. Third is name of loading image.
//   a.pause();      // Pause animation
//   a.restart();    // Restart a paused animation (do nothing if not paused)
//   a.start(imagearr);
//                   // Start animation. Takes an array of images that are
//                   // to be animated
//   a.stop();       // Stop animation, can't be restarted.
//   a.slow();       // Slow down animation
//   a.speed_up();   // Speed up animation
//   a.default_speed();
//                   // Reset to default speed.
//   a.previous();   // If paused, go back one frame.
//   a.next();       // If paused, go ahead one frame.
//   var f = a.current_image();
//                   // Return image currently displayed.
//   var on = a.am_on;
//   var paused = a.am_paused;
//   a.set_type(t);  // Set the type of animation, e.g., 
//                   // ANIMATE_FORWARD.
// -------------------------------------------------------------

var ANIMATE_FORWARD = 0, ANIMATE_FORWARD_BACKWARD = 1,
    ANIMATE_FORWARD_ONCE = 2;

// -------------------------------------------------------------
// Constructor.
// -------------------------------------------------------------

function Animation(i, n, li) {
    this.variable_name = n;
    this.image_name = i;
    this.loading_image = new Image();
    this.loading_image.src = li;
    this.speed = 0.3;
    this.am_on = false;
    this.am_paused = false;
    this.imagearr = 0;
    this.image_index = 0;
    this.pause = animation_pause;
    this.restart = animation_restart;
    this.start = animation_start;
    this.stop = animation_stop;
    this.current_image = animation_current_image;
    this.slow = animation_slow;
    this.speed_up = animation_speed_up;
    this.default_speed = animation_default_speed;
    this.previous = animation_previous;
    this.next = animation_next;
    this.update = animation_update_forward;
    this.update_image = animation_update_image;
    this.image_loaded = animation_image_loaded;
    this.set_timer = animation_set_timer;
    this.set_type = animation_set_type;
}

// -------------------------------------------------------------
// Restart animation if it has been paused.
// -------------------------------------------------------------

function animation_restart() {
    if(this.am_on && this.am_paused) {
	this.set_timer();
    }
}

// -------------------------------------------------------------
// Start animation.
// -------------------------------------------------------------

function animation_start(iarr) {
    this.stop();
    this.imagearr = iarr;
    this.image_index = 0;
    this.am_on = true;
    this.am_paused = false;
    if(document.images[this.image_name]) {
	document.images[this.image_name].src = this.loading_image.src;
    }
    this.set_timer();
}

// -------------------------------------------------------------
// Stop animation.
// -------------------------------------------------------------

function animation_stop() {
    if(this.am_on) {
	clearTimeout(this.timer_id);
	this.am_on = false;
	this.am_paused = false;
    }
}

// -------------------------------------------------------------
// Pause animation.
// -------------------------------------------------------------

function animation_pause() {
    if(this.am_on) {
	clearTimeout(this.timer_id);
	this.am_paused = true;
    }
}

// -------------------------------------------------------------
// Return current image.
// -------------------------------------------------------------

function animation_current_image() {
    return this.imagearr[this.image_index];
}

// -------------------------------------------------------------
// Adjust speed of animation.
// -------------------------------------------------------------

function animation_slow() {
    if(this.am_on &&
       !this.am_paused) {
	this.speed += 0.1;
	if(this.speed > 10) {
	    this.speed = 10;
	}
    }
}

function animation_speed_up() {
    if(this.am_on &&
       !this.am_paused) {
	this.speed -= 0.1;
	if(this.speed < 0.1) {
	    this.speed = 0.1;
	}
    }
}

function animation_default_speed() {
    this.speed = 0.3;
}

// -------------------------------------------------------------
// Go forward or backwards in animation.
// -------------------------------------------------------------

function animation_previous() {
    if(this.am_on && this.am_paused) {
	this.image_index--;
	if(this.image_index < 0) {
	    this.image_index = 0;
	}
	this.update_image();
    }
}

function animation_next() {
    if(this.am_on && this.am_paused) {
	this.image_index++;
	if(this.image_index >= this.imagearr.length) {
	    this.image_index = this.imagearr.length - 1;
	}
	this.update_image();
    }
}

// -------------------------------------------------------------
// Function that updates animation each time the timer times out.
// This goes forward, then wraps around to go forward again.
// -------------------------------------------------------------

function animation_update_wrapper(t) {
    t.update();
}

function animation_update_forward() {
    if(this.image_loaded()) {
	if(this.image_index >= this.imagearr.length - 1) {
	    this.pause_counter++;
	    if(this.pause_counter > 4) {
		this.image_index = 0;
	    }
	} else {
	    this.image_index++;
	    if(this.image_index >= this.imagearr.length - 1) {
		this.image_index = this.imagearr.length - 1;
		this.pause_counter = 0;
	    }
	}
	this.update_image();
    }
    this.set_timer();
}

// -------------------------------------------------------------
// This goes forward once.
// -------------------------------------------------------------

function animation_update_forward_once() {
    if(this.image_loaded()) {
	this.image_index++;
	if(this.image_index > this.imagearr.length - 1) {
	    this.image_index = 0;
	}
	this.update_image();
    }
    if(this.image_index < this.imagearr.length - 1) {
	this.set_timer();
    } else {
	this.pause();
    }
}

// -------------------------------------------------------------
// This goes forward, then backwards.
// -------------------------------------------------------------

function animation_update_forward_backward() {
    if(this.image_loaded()) {
	if(this.reverse) {
	    if(this.image_index <= 0) {
		this.pause_counter++;
		if(this.pause_counter > 3) {
		    this.reverse = false;
		}
	    } else {
		this.image_index--;
		if(this.image_index <= 0) {
		    this.image_index = 0;
		    this.pause_counter = 0;
		}
	    }
	} else {
	    if(this.image_index >= this.imagearr.length - 1) {
		this.pause_counter++;
		if(this.pause_counter > 3) {
		    this.reverse = true;
		}
	    } else {
		this.image_index++;
		if(this.image_index >= this.imagearr.length - 1) {
		    this.image_index = this.imagearr.length - 1;
		    this.pause_counter = 0;
		}
	    }
	}
	this.update_image();
    }
    this.set_timer();
}

// -------------------------------------------------------------
// Set type of animation to do.
// -------------------------------------------------------------

function animation_set_type(t) {
    if(t ==ANIMATE_FORWARD) {
	this.update = animation_update_forward;
    } else if(t ==ANIMATE_FORWARD_BACKWARD) {
	this.reverse = false;
	this.update = animation_update_forward_backward;
    } else if(t ==ANIMATE_FORWARD_ONCE) {
	this.update = animation_update_forward_once;
    } else {
	alert("Unrecognized type in animation_set_type: " + t);
    }
}

// -------------------------------------------------------------
// Update image displayed.
// -------------------------------------------------------------

function animation_update_image() {

// We do this test, because when first loading the page we can encounter
// the situation where update_animation is called before the page has been 
// fully loaded, so image isn't available yet.

    if(document.images[this.image_name]) {
	document.images[this.image_name].src = 
	    this.imagearr[this.image_index].src;
    }
}

// -------------------------------------------------------------
// Return true if all of the images have been loaded, 
// false otherwise. 
// -------------------------------------------------------------

function animation_image_loaded() {
    for(var i = 0; i < this.imagearr.length; ++i) {
	if(!this.imagearr[i].complete) {
	    return false;
	}
    }
    return true;
}

// -------------------------------------------------------------
// Set timer to update image.
// -------------------------------------------------------------

function animation_set_timer() {
    this.timer_id = setTimeout(this.variable_name + ".update()", 
			       this.speed * 1000);
}
