//---------------------------------------------------------------------
// ianime.js - Light-weight Animation module
//   version 0.28 (Dec. 12th, 2007)
//
// License:      MIT License
// Copyright:    Copyright (c) 2007-2008 Satoshi Nakajima
// Project Home: http://code.google.com/p/ianimejs/ 
//---------------------------------------------------------------------

var iAnime = function() {
    this.items = [];
};

// The rest of code in closure
(function(){
iAnime.effects = [];

function _move(e,r,x,y) {
    e.style.left = x + "px";
    e.style.top = y + "px";
}

function _noop() {}

function _poly(n) {
    if (_poly[n]) {
        return _poly[n];
    }
    var poly = [];
    var p = n+1;
    for (var i=0; i<n; i++) {
        p *= (i+1);
    }
    var l = p;
    var r = 1;
    for (var i=0; i<n; i++) {
        l = l/(n+1-i);
        r = r*(i+1);
        poly[i] = p/l/r;
    }
    // cache it
    _poly[n] = poly;
    return poly;
}

iAnime.prototype = {
    _citems: 0, _timer: 0, 
    paused: false,
    // Default parameters (can be overridden)
    delay: 33
};

iAnime.prototype.add = function(param)
{
    // Initialize missing/working parameters
    if (!param.duration) param.duration = 1;
    if (param.id) {
        param.element = document.getElementById(param.id);
    }
    if (param.element) {
        param._sx = param.element.offsetLeft;
        param._sy = param.element.offsetTop;
        param._draw = _move;
    } else {
        param._draw = _noop;
    }
    if (!('x' in param)) param.x = param._sx;
    if (!('y' in param)) param.y = param._sy;
    param._dx = param.x - param._sx;
    param._dy = param.y - param._sy;   
    param._st = this.paused ? this.pTime : (1*(new Date));

    // Check if a valid effect is specified
    if (param.effect && iAnime.effects[param.effect]) {
        param.move = (param._dx==0 && param._dy==0) ? _noop : _move;
        param._draw = iAnime.effects[param.effect];
        if (param._draw.init) {
            param._draw.init.call(param);
        }
    } 

    // Process Bezier control points, if any 
    if (param.cp) {
        var poly = _poly(param.cp.length);
        param._cx = [];
        param._cy = [];
        for (var i=0; i<param.cp.length; i++) {
            param._cx[i] = poly[i] * (param.cp[i].x-param._sx);
            param._cy[i] = poly[i] * (param.cp[i].y-param._sy);
        }
    }

    // We are ready now. Add this param to the list, draw the very first frame.
    this.items[this._citems++] = param;
    param._draw(param.element, 0, param._sx, param._sy);

    // Start the timer if necessary
    if (this.paused==false) {
        if (this._timer==0) {
            _startInterval(this);
        }
    }
    return param;
};

function _startInterval(self) {
    self._timer = setInterval(function() {_tick.call(self);}, self.delay);
}

function _stopInterval(self) {
    clearInterval(self._timer);
    self._timer = 0;
}

iAnime.prototype.addSequence = function(seq)
{
    if (seq.length==0) return;
    var item = seq.shift();
    if (item[0]) {
        // Nested sequence
        this.addSequence(item);
        this.addSequence(seq);
    } else {
        var self = this;
        var prev = item.onComplete;
        item.onComplete = function() { 
            if (prev) prev(item);
            self.addSequence(seq);
        } 
        this.add(item);
    }
}

iAnime.prototype.pause = function(pause)
{
  if (pause) {
    if (!this.paused) {
      if (this._timer) {
        _stopInterval(this);
      }
      this.pTime = 1*(new Date);
    }
  } else {
    if (this.paused && this._citems>0) {
      var duration = 1*(new Date) - this.pTime;
      for (var i=this._citems-1; i>=0; i--) {
        this.items[i]._st += duration;
      }
      _startInterval(this);
    }
  }
  this.paused = pause;      
}

function _tick()
{
    var now = 1*(new Date);
    for (var i = this._citems - 1 ; i >= 0 ; i--) {
        var item = this.items[i];
        var t = (now - item._st) / item.duration;
        if (t < 1) {
            if (item._draw.ratio) {
                t = item._draw.ratio(t);
            }
            if (item._cx) {
                var t1 = (1-t);
                var p = t;
                for (var j=0; j<item._cx.length; j++) {
                    p *= t1;
                }               
                var x = item._sx;
                var y = item._sy;
                for (var j=0; j<item._cx.length; j++) {
                    x += p * item._cx[j];
                    y += p * item._cy[j];
                    p = p/t1*t;
                }
                x += p * item._dx;
                y += p * item._dy;
                item._draw(item.element, t, x, y);
            } else {
                item._draw(item.element, t,
                    item._sx+item._dx*t, item._sy+item._dy*t);
            }
        } else {
            // Draw it with t=1.0 at the end
            item._draw(item.element, 1,
                item._sx+item._dx, item._sy+item._dy);
            this.items[i] = this.items[--this._citems];
            this.items[this._citems] = null;
            if (item.onComplete) {
                item.onComplete();
            }
        }
    }
    // Stop the timer if there is no animation
    if (this._citems==0) {
        _stopInterval(this);
    }
}
})();

