/**
 * Generic Timer
 * Every animation on the L'Arcada site seems to consist of the following parts:
 * 1.) Something must be displayed! 
 * 2.) Gradually display it
 * 3.) Let it sit for a while.
 * 4.) Repeat for the next object in the list
 * This script is intended to be a generic framework for such timers.
 */

/**
 * Generic_Timer
 * Constructor. Needs to know the following things:
 * >starting value for the "transition parameter" (opacity? position?)
 * >ending value for the transition parameter   
 * >how long to display each object
 * >how long between updates during the display animation
 * >how many display updates to perform during the animation
 * Also need some function pointers
 * >Function to call to display first object if animation does not start right away 
 * >Function to call when object animation starts 
 * >Function to call during object animation updates
 * >Function to call when object animation finishes
 * Note that all function pointers are optional. No need to write events you don't need!      
 */ 
function Generic_Timer(transition_start_value, transition_end_value, display_time, update_interval, transition_length, fp_display_first_object, fp_start_animation, fp_during_animation, fp_finish_animation)
{
  this.transition_value = 0;
  this.transition_start_value = transition_start_value;
  this.transition_end_value = transition_end_value;
  this.object_display_time = display_time;
  this.object_update_interval = update_interval;
  this.transition_time = transition_length;
  
  /* How much the transition value changes per update interval */
  /* Note that this becomes an INT value. If you want floats, edit this */
  this.increment_per_interval = parseInt((transition_end_value - transition_start_value) * (update_interval / transition_length));

  if (fp_display_first_object != null)
    this.displayFirstObject = fp_display_first_object
  else
    this.displayFirstObject = Null_Callback;
  
  if (fp_start_animation != null)
    this.animationStartCallback = fp_start_animation;
  else
    this.animationStartCallback = Null_Callback;
  
  if (fp_during_animation != null)  
    this.animationInProgressCallback = fp_during_animation;
  else
    this.animationInprogressCallback = Null_Callback;
  
  if (fp_finish_animation != null)
    this.animationCompleteCallback = fp_finish_animation;
  else
    this.animationCompleteCallback = Null_Callback;

  this.go = Start_Timer;
  this.initializeAnimationTiming = Initialize_Animation_Timing;
  this.startTransitionAnimation = Start_Transition_Animation;
  this.endTransitionAnimation = End_Transition_Animation;
  this.duringTransitionAnimation = During_Transition_Animation;
  this.Bind = Bind;
  
  this.ivlStartTransitionAnimation = null;
  this.tmrDuringTransitionAnimation = null;
}

/**
 * Start_Timer
 * Starts a timer running
 * @param mode 0, we display an object but do not transition
 *        mode 1, we transition into the first object  
 */  
function Start_Timer(mode)
{
  if (mode == 0)
  {
    this.displayFirstObject();
    setTimeout(this.Bind(this.initializeAnimationTiming), this.object_display_time);
  }
  else if (mode == 1)
  {
    this.initializeAnimationTiming();
  }
  
}

/**
 * Initialize_Animation_Timing
 * Sets up timing for all subsequent transition animations
 * Animation begins when this function is called 
 */  
function Initialize_Animation_Timing()
{
  this.ivlStartTransitionAnimation = setInterval(this.Bind(this.startTransitionAnimation), this.object_display_time + this.transition_time);
  this.startTransitionAnimation();

}

/**
 * Start_Transition_Animation
 * Occurs when we are about to transition to a new object
 */  
function Start_Transition_Animation()
{
//  this.ivlDuringTransitionAnimation = setInterval(this.animationInProgressCallback, this.object_update_interval);
//  setTimeout(this.Bind(this.endTransitionAnimation), this.transition_time);
  this.animationStartCallback();
  this.transition_value = this.transition_start_value;
  this.duringTransitionAnimation();
}

/**
 * During_Transition_Animation
 * Occurs at every preset interval during the transition animation
 */  
function During_Transition_Animation()
{
  var keep_animating = true;
  this.animationInProgressCallback(this.transition_value);
  this.transition_value += this.increment_per_interval; 
  if (this.increment_per_interval < 0 && this.transition_value <= this.transition_end_value)
    keep_animating = false;
  if (this.increment_per_interval >= 0 && this.transition_value >= this.transition_end_value)
    keep_animating = false;
  
  if (keep_animating)  
    this.tmrDuringTransitionAnimation = setTimeout(this.Bind(this.duringTransitionAnimation), this.object_update_interval);
  else
    this.endTransitionAnimation();
}

/**
 * End_Transition_Animation
 * Occurs at the end of the transition animation
 */  
function End_Transition_Animation()
{
  this.animationCompleteCallback();
}

/**
 * Null_Callback
 * Does absolutely nothing 
 */ 
function Null_Callback() {}

/** Thanks to pagecolumn.com for this! **/
function Bind(Method)
{
    var _this = this; 
    return( 
         function(){ 
            return( Method.apply( _this, arguments ) ); 
         } 
    ); 
}
