/*
 Animator
 
 Author: Makoto Kinoshita
 
 Copyright 2007 HMDT. All rights reserved.
*/


Function.prototype.bind = function(object)
{
    var method = this;
    return function() { return method.apply(object); }
}

function Animator()
{
    this.fromValue = 0.0;
    this.toValue = 1.0;
    this.currentValue = 0.0;
    this.duration = 500;
    this.direction = 0;
    this.startTime = 0;
    this.frameRate = 13;
    this.timer = null;
}

Animator.prototype.setHandler = function(handler)
{
    this.handler = handler;
}

Animator.prototype.setFinishHandler = function(handler)
{
    this.finishHandler = handler;
}

Animator.prototype.duration = function()
{
    return this.duration;
}

Animator.prototype.setDuration = function(duration)
{
    this.duration = duration;
}

Animator.prototype.frameRate = function()
{
    return this.frameRate;
}

Animator.prototype.setFrameRate = function(frameRate)
{
    this.frameRate = frameRate;
}

Animator.prototype.startAnimation = function(direction)
{
    if (direction != this.direction) {
        // Stop current animation
        this.stopAnimation();
        
        // Set start time
        this.startTime = (new Date).getTime() - this.frameRate;
        
        // Set values
        this.fromValue = this.currentValue;
        this.toValue = direction == 0 ? 0.0 : 1.0;
        this.direction = direction;
        
        // Start timer
        this.timer = setInterval(this.stepNextFrame.bind(this), this.frameRate);
    }
}

Animator.prototype.stopAnimation = function()
{
    if (this.timer) {
        // Stop timer
        clearInterval(this.timer);
        this.timer = null;
    }
}

Animator.prototype.stepNextFrame = function()
{
    // Calc elpased time
    var elpased = (new Date).getTime() - this.startTime;
    if (elpased < 0) elpased = 0;
    if (elpased > this.duration) elpased = this.duration;
    
    // When elpased time is larger than duration
    if (elpased >= this.duration) {
        // Stop animation
        this.stopAnimation();
        
        // Set opacity value
        this.currentValue = this.toValue;
    }
    else {
        // Calc opacity value
        var scale = 0.5 - (0.5 * Math.cos(Math.PI * elpased / this.duration));
        this.currentValue = computeNextFloat(this.fromValue, this.toValue, scale);
    }
    
    // Notify step
    if (this.handler != undefined && this.handler != null) {
        this.handler(this);
    }
    
    // Notify animation end
    if (elpased >= this.duration) {
        if (this.finishHandler != undefined && this.finishHandler != null) {
            this.finishHandler(this);
        }
    }
}

function computeNextFloat(from, to, ease)
{
    return from + (to - from) * ease;
}
