Animation.prototype.duration = 1;
Animation.prototype.prop = null;
Animation.prototype.obj = null;
Animation.prototype.startValue = 0;
Animation.prototype.endValue = 1;
Animation.prototype.ease = true;
Animation.prototype.timerSB = null;
Animation.prototype.name = null;
Animation.prototype.compoundAnimation;
Animation.prototype.lastFraction = -1;
Animation.prototype.IsPlaying = false;

var Linear = 0;
var Wiggle = 1;

Animation.prototype.type = Linear;

function Animation(theName, theObj, theProp, theStartVal, theEndVal, theDuration)
{
    this.name = theName;
    this.obj = theObj;
    this.prop = theProp;
    this.startValue = theStartVal;
    this.endValue = theEndVal;
    this.duration = theDuration;
    
    this.timerSB = MainCanvas.findname("TimerSB");
}

Animation.prototype.GetValue = function(theFrac)
{
    //Debug("GetValue    this = " + this.name + "    theFrac = " + theFrac);
    var frac = theFrac;
    
    if (frac < 0)
        frac = 0;
    
    if (frac > 1)
        frac = 1;
    
    if (this.easeFunction != null)
    {
        var valOut = this.easeFunction(frac);
        frac = valOut;
    }
    else if (this.ease)
        frac = easeInOut(frac);
        
    this.fraction = frac;
    var rc = frac;
    
    if (this.type == Linear)
    {
        rc = this.startValue + (this.endValue - this.startValue) * frac;
    }
    else if (this.type == Wiggle)
    {
        rc = this.startValue + (this.endValue - this.startValue) * Math.sin(3 * 2 * Math.PI * frac);
    }    
        
    return rc;
}

Animation.prototype.easeFunction = null;

function easeInOut(valIn)
{
    return Math.sin(valIn * Math.PI/2);
}

Animation.prototype.Process = function(_frac)
{
    var frac = _frac;
    
    if (this.OnPreFractionScript != null)
    {
        frac = this.OnPreFractionScript(_frac);
    }
    
    var val = this.GetValue(frac);
     
    this.currentValue = val;
    
    if (this.obj != null && this.prop != null)
    {
        //Debug("????? prop " + this.prop + " obj = " + this.obj + "       val = " + val);
        this.obj[this.prop] = val;
    }
    
    if (this.OnSyncScript != null)
    {
        //dd("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + this.OnSyncScript);
        this.OnSyncScript();
    }

    
    if (this.OnFractionScript != null)
        this.OnFractionScript(this);
 
    
    if (this.OnPostFractionScript != null)
        this.OnPostFractionScript(frac);       
      
    this.lastFraction = frac;
}

Animation.prototype.startTime = -1;
Animation.prototype.time = -1;
Animation.prototype.fraction = -1;
Animation.prototype.completedToken = null;
Animation.prototype.currentValue = -1;

Animation.prototype.OnFractionScript = function(anim)
{
}
Animation.prototype.OnPostFractionScript = null;
Animation.prototype.OnPreFractionScript = null;


Animation.prototype.OnSyncScript = function()
{
}

Animation.prototype.AnimationIndex = 0;

Animation.prototype.Play = function()
{  
    this.AnimationIndex = AddRunningAnimation(this);
    //alert("this.AI = " + this.AnimationIndex +"      name = " + this.name);
    
    if (this.OnPlayScript != null)
    {
        this.OnPlayScript();
    }
    if (this.OnPlayScript2 != null)
    {
        this.OnPlayScript2();
    }    
    if (this.OnPlayAnimation != null)
    {
        this.OnPlayAnimation.Play();
    }
    
    if (this.PlayAnimations != null && this.PlayAnimations.length > 0)
    {
        for (var ii = 0; 
            ii < this.PlayAnimations.length; 
            ii++)
        {
            //alert(this.name + " playing " + this.PlayAnimations[ii].name + " (" + ii + ") of " + this.PlayAnimations.length);
            this.PlayAnimations[ii].Play();
        }
    }
    
    this.startTime = (new Date()).getTime();
    
    if (!useJSTimer)
    {
        // OnCompleted gets called outside the context of an Animation object!
        var del = Silverlight.createDelegate(this, this.OnCompleted);
        
        this.completedToken = this.timerSB.addEventListener("Completed", del );

        this.timerSB.Begin();
    }
    
    this.IsPlaying = true;
}

Silverlight.createDelegate = function(instance, method) {
	return function() {
        return method.apply(instance, arguments);
    }
}

Animation.prototype.OnCompleted = function(sender, e)
{
    this.Tick();
    
}

Animation.prototype.Tick = function()
{
    if (useJSTimer)
    {
        if (this.AnimationIndex == -1) alert("shouldn't be. name = " + this.name + " runnSize = " + runningAnimations.length);
    }
    
    var currTime = (new Date()).getTime();
    this.time = (currTime - this.startTime) / 1000.0;
    //Debug("this.startTime = " + this.startTime + " this.time = " + this.time + "        this.fraction = " + this.fraction);
    
    this.fraction = this.time / this.duration; 
    
    if (this.fraction > 1)
    {
        this.fraction = 1;
        this.Stop();
    }
    
    if (this.fraction < 0)
        this.fraction = 0;
        
    this.Process(this.fraction);
}

Animation.prototype.Stop = function()
{
    if (this.completedToken != null)
        this.timerSB.removeEventListener("Completed", this.completedToken);

    if (useJSTimer)
    {
        var oldAI = this.AnimationIndex;
        
        if (this.AnimationIndex != -1)
        {
            var r1 = runningAnimations.length;
            //alert("stopped index = " + this.AnimationIndex + "    still running: " + runningAnimations.length);
            RemoveRunningAnimation(this); 
            
            var r2 = runningAnimations.length;
            if (r2 != (r1 - 1)) alert("" + r1 + "   vs   " + r2);
        }   
    }
    
    if (this.compoundAnimation != null)
    {
        //alert("comp!");
        this.compoundAnimation.OnStop();
    }           
    
    if (this.OnStopAnimation != null)
    {
        //alert("this.OnStopAnimation = " + this.OnStopAnimation.name + " this.AnimationIndex = " + oldAI);
        this.OnStopAnimation.Play();
    } 
    
    if (this.OnStopScript != null)
        this.OnStopScript();
        
    if (this.OnStopScript2 != null)
        this.OnStopScript2();  
        
    this.IsPlaying = false;    
}

Animation.prototype.OnPlayAnimation = null;
Animation.prototype.OnStopAnimation = null;

Animation.prototype.OnPlayScript = null;
Animation.prototype.OnPlayScript2 = null;
Animation.prototype.OnStopScript = null;
Animation.prototype.OnStopScript2 = null;

Animation.prototype.PlayAnimations = null;

Animation.prototype.AddPlayAnimation = function(anim)
{
    if (this.PlayAnimations == null) this.PlayAnimations = new Array();
    this.PlayAnimations.push(anim);
}
//---------------------------------------

CompoundAnimation.prototype.animations = null;
CompoundAnimation.prototype.easeFunction = null;
CompoundAnimation.prototype.baseAnimation = null;
CompoundAnimation.prototype.stops = null;
CompoundAnimation.prototype.AnimationIndex = -1;

function CompoundAnimation()
{
    this.animations = new Array();
    this.stops = new Array();
    this.baseAnimation = new Animation("comp", null, null, 0, 1, 1);
    this.baseAnimation.OnSyncScript = Silverlight.createDelegate(this, this.OnFraction);
    this.baseAnimation.OnStopScript = Silverlight.createDelegate(this, this.OnStop);
    this.baseAnimation.compoundAnimation = this;
    //this.baseAnimation.OpStopScript();
}

CompoundAnimation.prototype.Add = function(anim)
{
    this.animations.push(
        //anim
        Silverlight.createDelegate(anim, anim.Process)
        );
        
    this.stops.push(Silverlight.createDelegate(anim, anim.Stop));
}

CompoundAnimation.prototype.Play = function()
{
    //alert("c.play");
    this.baseAnimation.Play();
}

CompoundAnimation.prototype.OnFraction = function()
{
    for (var i = 0; i < this.animations.length; i++)
    {
        var ff = this.baseAnimation.fraction;
        if (ff >= 1)
            ff = 1;
            
        //Debug("OnFraction.   this = " + this.constructor + "      this.fraction = " + this.baseAnimation.fraction);
        this.animations[i](  ff              );//.Process(inVal);  
    }
}

CompoundAnimation.prototype.OnCompleteScript = null;

CompoundAnimation.prototype.OnStop = function()
{
    //alert("ss");
    for (var i = 0; i < this.animations.length; i++)
    {
        //Debug("OnFraction.   this = " + this.constructor + "      this.fraction = " + this.baseAnimation.fraction);
        this.stops[i]();  
    }
    
    runningAnimations.pop(this.AnimationIndex);
    
    if (this.OnCompleteScript != null)
        this.OnCompleteScript();
}