// FreeStyler Library // Copyright 2009 Ian Porter

function fsMorph(parent,newStyle,timePeriod,swooshStyle)
{
    this.index = this.all.length;
    this.all[this.index] = this;
    this.parent = parent;
    this.newStyle = newStyle;
    this.timePeriod = timePeriod ? timePeriod : 1000;
    this.swooshStyle = swooshStyle;
}

fsMorph.prototype.all = new Array();


fsMorph.prototype.isBusy = function()
{
    return this.loopId ? true : false;
}

fsMorph.prototype.stopMorph = function()
{
    if(this.loopId)
    {
        clearTimeout(this.loopId);
        this.loopId = null;
    }
}

fsMorph.prototype.isAtStart = function()
{
    return this.linear==0.0;
}
fsMorph.prototype.isAtEnd = function()
{
    return this.linear==1.0;
}


fsMorph.prototype.init = function()
{
    if(this.style)
        return true;

    // parent can be css rule name or element id
    this.style = fsGetRuleStyle(this.parent);
    if(!this.style)
    {
        var parentElement = document.getElementById(this.parent);
        if(parentElement)
            this.style = parentElement.style;
    }
    if(!this.style)
    {
        fsError.log("Can not find parent: " + this.parent);
        return false;
    }

    // new style can be css rule name or css text
    var newStyleRule = fsGetRuleStyle(this.newStyle);
    var cssText = newStyleRule ? newStyleRule.cssText : this.newStyle;    

    var styles = cssText.split(";");
    this.styleVars = new Array();
    for(var i in styles)
    {
        var bits = styles[i].split(":");
        if(bits.length==2)
        {
            this.styleVars[i] = new fsStyleVar(parentElement,this.style,bits[0],bits[1]);
            this.styleVars[i].init();  // set start values
            // note : if new style is css text and parent is element then styles should be declared inline on the element
        }
    }

    this.linear = 0.0;
    
    return true;
}


fsMorph.prototype.go = function(dir)
{
    if(!this.init())
        return;
    if(this.isBusy())
        return;
    if((dir>0 && !this.isAtStart()) || (dir<0 && !this.isAtEnd()))
        return;

    if(dir)
        this.dir = dir;
    else if(this.isAtStart())
        this.dir = 1;
    else if(this.isAtEnd())
        this.dir = -1;

    this.startTime = new Date().getTime();
    this.endTime = this.startTime + this.timePeriod;
    this.step();
}


fsMorph.prototype.step = function()
{
    // where are we?
    var currentTime = new Date().getTime();
    if(this.dir>0)
        this.linear = Math.min( 1, (currentTime-this.startTime)/this.timePeriod );
    else
        this.linear = Math.max( 0, (this.endTime-currentTime)/this.timePeriod );

    // apply new values
    if(this.styleVars!=null)
        for (var i in this.styleVars)
            this.styleVars[i].step(this.getSwoosh());
    
    // continue
    if( (this.dir>0 && this.linear<1.0) || (this.dir<0 && this.linear>0.0) )
    {    
        this.loopId = setTimeout( "fsMorph.prototype.all["+this.index+"].step();" , 15 ); // 1000/15 Hz
        return;
    }

    // finished 
    this.loopId = null;
    var seq = this.sequence;
    this.sequence = null;
    if(seq && seq.next)
        seq.next();
    else if(typeof seq == 'function')
        seq.call();
    else if(typeof seq == 'string')
        eval(seq);
}



fsMorph.prototype.getSwoosh = function()
{
    if(this.swooshStyle=='smooth')
        return ( 1 - Math.cos(Math.PI*this.linear) ) / 2;
    return this.linear;
}


