/**
 * File: animation.js
 *
 * An Animation object.
 *
 * Usage:
 *   <script type="text/javascript" src="http://www.bgsu.edu/scripts/animation.js">
 *   </script>
 *
 * Example:  animationTest1.html
 *   <!-- load animation.js -->
 *   <script type="text/javascript" src="http://www.bgsu.edu/scripts/animation.js">
 *   </script>
 *   <!-- a juggler -->
 *   <script type="text/javascript">
 *     var juggler = new Animation();
 *     juggler.addFrame( "http://www.bgsu.edu/scripts/juggler0.gif" );
 *     juggler.addFrame( "http://www.bgsu.edu/scripts/juggler1.gif" );
 *     juggler.addFrame( "http://www.bgsu.edu/scripts/juggler2.gif" );
 *     juggler.addFrame( "http://www.bgsu.edu/scripts/juggler3.gif" );
 *     juggler.setAlt( "The Juggler!" );
 *     juggler.setDelay( 200 );  // delay in milleseconds
 *     juggler.write();
 *     juggler.start();
 *   </script>
 *
 * Example:  animationTest2.html
 *   <!-- load animation.js -->
 *   <script type="text/javascript" src="http://www.bgsu.edu/scripts/animation.js">
 *   </script>
 *   <!-- a fast juggler, counterclockwise -->
 *   <script type="text/javascript">
 *     var jugglerLeft = new Animation();
 *     jugglerLeft.addFrame( "http://www.bgsu.edu/scripts/juggler0.gif" );
 *     jugglerLeft.addFrame( "http://www.bgsu.edu/scripts/juggler1.gif" );
 *     jugglerLeft.addFrame( "http://www.bgsu.edu/scripts/juggler2.gif" );
 *     jugglerLeft.addFrame( "http://www.bgsu.edu/scripts/juggler3.gif" );
 *     jugglerLeft.setAlt( "Juggle to the left..." );
 *     jugglerLeft.setDelay( 25 );  // delay in milleseconds
 *     jugglerLeft.write();
 *     jugglerLeft.start();
 *   </script>
 *   <!-- a stationary juggler -->
 *   <img src="http://www.bgsu.edu/scripts/juggler1.gif" 
 *        alt="I don't know how to juggle!">
 *   <!-- a fast juggler, clockwise -->
 *   <script type="text/javascript">
 *     var jugglerRight = new Animation();
 *     jugglerRight.addFrame( "http://www.bgsu.edu/scripts/juggler3.gif" );
 *     jugglerRight.addFrame( "http://www.bgsu.edu/scripts/juggler2.gif" );
 *     jugglerRight.addFrame( "http://www.bgsu.edu/scripts/juggler1.gif" );
 *     jugglerRight.addFrame( "http://www.bgsu.edu/scripts/juggler0.gif" );
 *     jugglerRight.setAlt( "Juggle to the right..." );
 *     jugglerRight.setDelay( 25 );  // delay in milleseconds
 *     jugglerRight.write();
 *     jugglerRight.start();
 *   </script>
 *
 */

/**
 * A static array of <em>all</em> Animation objects.
 *
 */
Animation.animations = new Array();

/**
 * An Animation object constructor.
 *
 */
function Animation() {

  // initialize frames array:
  this.frames = new Array();

  // initialize the properties of this Animation object:
  this.delay = 200;  // default delay
  this.numImagesLoaded = 0;  // counter for onload handler
  this.alt = "Animation";  // default alt attribute

  // store this Animation object in the animations array:
  this.animationID = Animation.animations.length;
  Animation.animations[ this.animationID ] = this;

}

/**
 * Add a frame to this Animation object.
 *
 */
Animation.prototype.addFrame = function( url ) {

  var n = this.frames.length;
  this.frames[ n ] = url;

}

/**
 * A setter method for the delay property of
 * this Animation object.
 *
 */
Animation.prototype.setDelay = function( delay ) {

  // validate argument and set delay property:
  var regexp = /^\d+$/;
  if ( regexp.test( delay ) ) {
    this.delay = delay;
  } else {
    window.alert( "Invalid argument to setDelay method: " + delay);
  }

}

/**
 * A setter method for the alt property of
 * this Animation object.
 *
 */
Animation.prototype.setAlt = function( alt ) {

  this.alt = alt;

}

/**
 * A method to write the initial frame of this Animation object 
 * into the current document.
 *
 */
Animation.prototype.write = function() {

  // compute index into images array (for recursive method):
  this.imageID = document.images.length;

  // write img tag into the current document:
  //window.alert( "this.images[0].width = " + this.images[0].width );
  //window.alert( "this.images[0].height = " + this.images[0].height );
  //this.width = this.images[0].width;
  //this.height = this.images[0].height;
  document.write( '<img src="' + this.frames[0] + '"' );
  //document.write( ' width="' + this.width + '" height="' + this.height + '"' );
  //document.write( ' alt="animations[' + this.animationID + ']"' );
  document.write( ' alt="' + this.alt + '"' );
  document.write( ' border="0">' );

}

/**
 * A method to initiate the animation of
 * this Animation object.
 *
 */
Animation.prototype.start = function() {

  // initialize images array:
  var n = this.frames.length;
  this.images = new Array( n );

  // load images array:
  for ( var i = 0; i < n; i++ ) {
    this.images[i] = new Image();
    this.images[i].animation = this;
    this.images[i].onload = countImages;
    this.images[i].src = this.frames[i];
  }

}

/**
 * An image onload handler.
 *
 */
function countImages() {
  var numImagesLoaded = ++this.animation.numImagesLoaded;
  var numImages = this.animation.images.length;
  if ( numImagesLoaded == numImages ) {
    var width = this.animation.images[0].width;
    var height = this.animation.images[0].height;
    for ( var i = 1; i < numImages; i++ ) {
      if ( width != this.animation.images[i].width || height != this.animation.images[i].height ) {
        window.alert( "Images have incompatible dimensions!" );
        break;
      }
    }
    // initiate recursion:
    var id = this.animation.animationID;
    Animation.animations[ id ].displayNextFrame( 1 );
  }
}

/**
 * A recursive method that displays the next frame of
 * this Animation object.
 *
 */
Animation.prototype.displayNextFrame = function( n ) {
  n %= this.images.length;
  document.images[ this.imageID ].src = this.images[ n ].src;
  var id = this.animationID;
  var codeStr = "Animation.animations[" + id + "].displayNextFrame(" + (n+1) + ")";
  setTimeout( codeStr, this.delay );
}