function Animation()
{
    this.type = "Animation"
    this.element = null;
    this.isFinished = false;
    this.params = {style:null,to:null,behavior:null} 
    this.frames = new Array()
    this.frameFunctions = new Array()
    this.curFrame = 0
    this.f = null
    //function prototypes
    this.execute = execute;
    this.animate = animate;
    this.setFrameFunction = setFrameFunction;
    this.setParameters = setParameters;
    this.setFrames = setFrames
    this.initialize = initialize
    
    
    //if the two constructors are not used, then the setFunctions are assumed
    if(!Animation.arguments[0])
    {
        //this is the case for the global instance ANIMATOR used for type info
        return
    }
    if(Animation.arguments[0] && !Animation.arguments[1])
    {
        var obj = Animation.arguments[0]
        for(var i in obj)
        {
            if(i == "element")
                this.element = obj[i]
            else
            {
                this.params[i] = obj[i]
                if(i.indexOf("f") == 0)
                {
                    this.frameFunctions[i] = obj[i]
                }
            }
        }
        this.params.isSet = true
        this.initialize();
    }
    else if(Animation.arguments[0] && Animation.arguments[1])
    {
        var obj = Animation.arguments[1]
        this.element = Animation.arguments[0]
        for(var i in obj)
        {
            this.params[i] = obj[i]
            if(i.indexOf("f") == 0)
            {
                this.frameFunctions[i] = obj[i]
            }
        }
        this.params.isSet = true
        this.initialize();
    }
    
    
    
    
    ///////////////////////////////////////////
    //            Member Functiosn           //
    ///////////////////////////////////////////
    
    function setFrameFunction(frame,func)
    {
        this.frameFunctions[frame] = func
    }
    
    function setElement(node)
    {
        this.element = node;
        if(this.params.isSet && this.params.type)
        {
            this.initialize()
        }
    }
    
    function setParameters(newParams)
    {
        for(var i in newParams)
        {
            this.params[i] = newParams[i];
        }
        this.params.isSet = true
        if(this.element != null && this.params.type)
        {
            this.initialize()
        }
    }
    
    function setFrames(interval,isColor)
    {
        var scale = 1/100.0
        if(isColor)
        {
            
            for(var i = 0; i < this.params.behavior.frameCount;i++)
            {
                var valr = this.VI.r + interval.r*this.f[i]*scale
                var valg = this.VI.g + interval.g*this.f[i]*scale
                var valb = this.VI.b + interval.b*this.f[i]*scale
                this.frames.push({r:valr,g:valg,b:valb})
            }
        }
        else
        {
            
            for(var i = 0; i < this.params.behavior.frameCount;i++)
            {
                var val = this.VI + interval*this.f[i]*scale
                this.frames.push(val)
            }
        }
    }
    
    
    function initialize()
    {
        if(this.params.behavior.split)
            this.params.behavior = new Behavior(this.params.behavior)
        var FC = this.params.behavior.frameCount
        var style = this.params.style
        var vf = this.params.to
        var unit = null
        var interval = null
        this.f = this.params.behavior.getArray()
        if(style.indexOf("color") != -1 || style.indexOf("Color") != -1)
        {
            //its a color, otherwise it is assumed to be a unit in the System class's getUnit function
            unit = null
            var c = this.element.style[style]
            this.VI = {r:parseInt(c.substr(0,2),16),g:parseInt(c.substr(2,4),16),b:parseInt(c.substr(4,6),16)}
            c = this.params.to
            vf = {r:parseInt(c.substr(0,2),16),g:parseInt(c.substr(2,4),16),b:parseInt(c.substr(4,6),16)}
            
            interval = {r:vf.r-this.VI.r,g:vf.g-this.VI.g,b:vf.b-this.VI.b}
            this.setFrames(interval,true)
            
        }
        else
        {
            unit = GLOBAL["SYSTEM"].getUnit(this.element.style[style])
            this.VI = parseFloat(this.element.style[style])
            interval = vf-this.VI
            this.setFrames(interval,false)
        }
    }
    
    function animate(frame)
    {
        var FC = this.params.behavior.frameCount
        var style = this.params.style
        var vf = this.params.to
        var unit = null
        var vi = null
        var vn = null
        var interval = null
        if(style.indexOf("color") != -1 || style.indexOf("Color") != -1)
        {
            unit = null  
            vn = GLOBAL["SYSTEM"].toHex(this.frames[frame].r) +
                 GLOBAL["SYSTEM"].toHex(this.frames[frame].g) +
                 GLOBAL["SYSTEM"].toHex(this.frames[frame].b)
            this.element.setStyle(style,vn)
        }
        else
        {
            unit = GLOBAL["SYSTEM"].getUnit(this.element.style[style])
            vi = String(this.frames[frame])+unit
            
            this.element.setStyle(style,vi)
        }
    }
    
    function execute()
    {
        //check if this element is already being animated for this style
        if(this.element.semaphore[this.params.style] == -1)
        {
            //set it, else it is set, and that animation needs to be removed from
            //the animator
            this.element.semaphore[this.params.style] = this
        }
        else
        {
            //remove previous animation
            if(this.element.semaphore[this.params.style] != this)
                GLOBAL["ANIMATOR"].removeAnimation(this.element.semaphore[this.params.style])
            //setup this one
            this.element.semaphore[this.params.style] = this
        }
        if(this.curFrame < this.params.behavior.frameCount)
        {
            this.animate(this.curFrame)
            if(this.frameFunctions["f"+this.curFrame])
            {
                if(this.frameFunctions["f"+this.curFrame].type == ANIMATION.type)
                {
                    GLOBAL["ANIMATOR"].registerAnimation(this.frameFunctions["f"+this.curFrame])
                }
                else
                {
                    //it is assumed to be a function with no arguments
                    //to get one with arguments use a closure to set the frame function
                    this.frameFunctions["f"+this.curFrame]()
                }
            }
            this.curFrame += 1
        }
        else {
            this.element.semaphore[this.params.style] = -1
            this.isFinished = true
            }
    }
    
}


var ANIMATION = new Animation()
