/* Expects a global variable "animation_zero_image". */
/**
 * cnImageFrameset Object constructor.
 * @param imagelistArray   Array of cnImageFrames.
 * @param width            Size of image
 * @param height           Size of image
 * @param target_div       Div element name to insert the animation to
 */
function cnImageFrameset ( imagelistArray, w, h, target_div, clickable )
{
   /*
    * Image
    */
   this.imageElement = document.createElement("img");
   if ( ! this.imageElement )
      throw "Can't create img element";
   with ( this.imageElement )
   {
      width    = w;
      height   = h;
      alt      = "Animation image";
      title    = "Click to play and stop";
   }
   this.imageElement._this    = this;
   if ( clickable )
      this.imageElement.onclick  = this.click_default;
   // set image initially to first in list.
   if ( imagelistArray.length > 0 )
      this.imageElement.src = imagelistArray[0].src;
   
   // attatch image
   var target_div_elem = document.getElementById(target_div);
   if ( ! target_div_elem )
      throw "Can't find target div";
   target_div_elem.appendChild(this.imageElement);
   
   /*
    * Tracker div
    */
   this.tracker_div_element = document.createElement("div");
   if ( ! this.tracker_div_element )
      throw "Can't make tracker div";
   this.tracker_div_element.className = "tracker";
   target_div_elem.appendChild(this.tracker_div_element);
   
   /*
    * Elements
    */
   this.cnImageList = imagelistArray;
   for ( var i = 0; i < this.count(); i++ )
      this.cnImageList[i].register(this, i);
   
   /*
    * Start loading images (load 2 at once)
    */
   this.load_next_image();
   this.load_next_image();
}
cnImageFrameset.prototype = {
   
   /**
    * Timeout between frames in ms
    */
   delay:
      300,
   
   /**
    * Frame currently displayed
    */
   currentFrame:
      0,
   
   /**
    * Set to true to loop
    */
   loop:
      false,
   
   /**
    * True if animating, false if paused or stopped.
    */
   is_animating:
      false,
   
   /**
    * True if waiting for next image to load before continuing.
    */
   is_waiting:
      false,
   
   /**
    * Count items in cnImageList
    * @return              Number of items
    */
   count: function ()
   {
      if ( !this.cnImageList )
         return 0;
      return this.cnImageList.length;
   },
   
   /**
    * Get an cnImageFrame for the frame ID
    * @param num           frame ID (number)
    * @return              cnImageFrame or null
    */
   get_image_frame: function ( num )
   {
      if ( this.count() < num || num < 0 )
         return null;
      return this.cnImageList[num];
   },
   
   /**
    * Show an image
    * @param num           Frame ID (number) to display
    * @return              True on success, false on failure
    */
   show_image: function( num )
   {
      var item = this.get_image_frame(num);
      if ( ! item )           return false;
      if ( item.timedout )    return true; // pretend it's ok
      if ( ! item.loaded )    return false;
      
      this.imageElement.src = item.src;
      
      //highlight 
      for ( var i = 0; i < this.count(); i++ )
      {
         this.get_image_frame(i)
             .select_trackerblip(i == num);
      }

      return true;
   },
   
   /**
    * Start animation
    * @param start         Frame ID to start from. Negative for "resume".
    */
   animate: function( start )
   {
      if (start >= 0)
         this.currentFrame = start;
      
      // force continue
      this.is_waiting = false;
      
      // if not running, do it.
      if ( ! this.is_animating )
      {
         this.is_animating = true;
         this.show_frame_and_continue(this);
      }
   },
   
   /**
    * Stop animation
    */
   animate_stop: function()
   {
      this.is_animating = false;
      window.clearTimeout(this.timeout_item);
   },
   
   /**
    * Shows this.currentFrame if possible and schedules next frame in sequence
    * This is sometimes passed from events, so this is passed as an argument as _this.
    */
   show_frame_and_continue: function( _this )
   {
      if ( ! _this.is_animating)
         return; // something has asked the frame sequence to stop.
      
      if ( _this.show_image( _this.currentFrame ) )
      {
         //frame displayed - increment and wait
         if ( ++ _this.currentFrame >= _this.count() )
         {
            if (_this.loop)
            {
               _this.currentFrame = 0;
            }
            else 
            {
               _this.animate_stop();
               return;
            }
         }
         
         this.timeout_item = window.setTimeout(function () { _this.show_frame_and_continue(_this) }, _this.delay);
      }
      else
      {
         //frame not displayed
         _this.is_waiting = true;
      }
   },
   
   /**
    * Resume after waiting
    */
   resume_from_waiting: function()
   {
      this.is_waiting = false;
      this.show_frame_and_continue(this);
   },
   
   /**
    * Loads the next image in the list
    */
   load_next_image: function()
   {
      for ( var i = 0; i < this.count(); i++ )
      {
         if ( this.cnImageList[i].requested == false )
         {
            this.cnImageList[i].load_image();
            return;
         }
      }
   },
   
   
   
   /* PRIVATE */
   
   /**
    * return from setTimeout
    */
   timeout_item:
      0,
   
   /**
    * Array of cnImageFrames
    */
   cnImageList:
      null,
   
   /**
    * Element for HTML IMG
    */
   imageElement:
      null,
   
   /**
    * Element for HTML DIV to place tracker blips
    */
   tracker_div_element:
      null,
   
   
   
   /* CALLBACK */
   
   /**
    * Default "click" behaviour.
    * This is a response to ONCLICK so "this" is "imageElement".
    */
   click_default: function ()
   {
      //get_this()
      var _this = this;
      if (this._this)
         _this = this._this;
      
      if ( _this.is_animating )
      {
         _this.animate_stop();
      }
      else
      {
         _this.animate ( ( _this.currentFrame < _this.count() ) ? -1 : 0 );
      }
   }//,
};

