var animList = new Array();

// The One animation function
function animate(animId, duration, delay, run, end, step){
    var anim = new Object;

    if(!run){
        return false;
    }else{
        anim.run = run;
    }

    if(end){
        anim.end = end;
    }

    anim.startStep = Math.round(delay * 1000 / animationInterval);

    anim.steps = (duration) ? Math.round(duration * 1000 / animationInterval) : Math.round(1000 / animationInterval);

    anim.step = step || 1;

    if(!showAnimations){
        anim.step = anim.steps;
    }

    anim.id = animId;

    var i = findActive(animId);

    if(i != -1){
        animList[i] = anim;
        alert(animList[i].id);
    }else{
        animList[animList.length] = anim;
    }

    delete anim;

    if(!window.animation){
        window.animation = window.setInterval(
            function(){
                for(var i = 0; i < animList.length; i++){
                    var anim = animList[i];

                    if(anim && !anim.startStep){
                        anim.run(anim.steps, anim.step);
                        anim.step++;
                    }else if(anim){
                        anim.startStep--;
                    }

                    if(anim && anim.step > anim.steps){
                        if(typeof(anim.end) == 'function'){
                            anim.end();
                        }
                        animList.splice(i, 1);
                        anim = null;
                    }
                }

                if(animList.length == 0){
                    window.clearInterval(window.animation);
                    window.animation = null;
                }
            }, animationInterval);
    }
}

// Returns animId's index if it's running, -1 if not
function findActive(animId){
    for(var i = 0; i < animList.length; i++){
        if(animList[i] && animList[i].id == animId){
            return i;
        }
    }

    return -1;
}

// Stops an animation if it's running
function stopAnim(animId){
    var i = findActive(animId);
    if(i != -1){
        animList.splice(i, 1);
    }
}

// Return a value for a 'frame' in an animation
function easeInOut(min, max, steps, step, power, direction, isFloat){
    power = power || 1;

    if(direction == 'out'){
        //Generic animation step value generator by Craig Laparo
        var a = (min - max) / Math.pow(steps, power);
        var y = parseInt(a * Math.pow((steps - step), power) + max);
    }else if(direction == 'in'){
        //Generic Animation Step Value Generator By www.hesido.com
        var delta = max - min;
        var y = min + (Math.pow(((1 / steps) * step), power) * delta);
    }else{
        //Sinoidal animation function from scriptaculous, adapted by Craig Laparo
        var pos = step / steps;
        var y = min + (max - min) * ((-Math.cos(pos * Math.PI) / 2) + 0.5);
    }

    return isFloat ? y : Math.ceil(y);
}

// Generic slide function
function slide(id, direction, min, max, duration, power, delay){
    var animId = id + 'Slide';
    stopAnim(animId);

    var element = $(id);
    if(!element){
        return false;
    }

    var step = 1;
    var steps = Math.round(duration * 1000 / animationInterval);

    element.originalWidth = element.originalWidth || parseInt(element.style.width);

    if(direction == 'in'){
        element.style.display = '';
    }

    duration = duration || 1;

    power = power || 1;

    delay = delay || 0;

    var step = 1;

    if(findActive(animId) != -1){
        var current = parseInt(element.style.width);
        for(step; step < steps; step++){
            var test = easeInOut(min, max, steps, step, power, direction, true);
            if(direction == 'in' && test >= current || direction != 'in' && test <= current){
                break;
            }
        }
    }

    var run = function(steps, step){element.style.width = easeInOut(min, max, steps, step, power, direction, true) + '%';};
    if(direction != 'in'){
        var end = function(){element.style.display = 'none';};
    }

    animate(animId, duration, delay, run, end, step);
}

function bgAnimate(element, frames, increment, interval, orientation, direction){
// Generic background position animator by Craig Laparo

    if(element.bgAnimate){
        window.clearInterval(element.bgAnimate);
    }

    if(element.style.backgroundPosition){
        var bgPos = element.style.backgroundPosition.split(' ');
        var xy = (orientation == 'x') ? 0 : 1;
        var other = (orientation == 'x') ? bgPos[1] : bgPos[0];
        var startFrame = -1 * parseInt(bgPos[xy]) / increment;
    }else{
        var startFrame = 0;
        var other = 0;
    }

    if(orientation == 'x'){
        var prefix = '-';
        var suffix = 'px ' + other;
    }else{
        var prefix = other + ' -';
        var suffix = 'px';
    }

    direction = direction || 1;

    element.bgAnimate = window.setInterval(
        function(){
            element.style.backgroundPosition = prefix + (increment * startFrame) + suffix;
            startFrame += direction;
            if(startFrame > frames || startFrame < 0){
                window.clearInterval(element.bgAnimate);
            }
        }, animationInterval);
}

function highlightIn(){
    if(!this.currentbgRGB){
        this.link = this.getElementsByTagName('A')[0];
        this.currentbgRGB = linkBG1;
        this.link.currentfgRGB = linkFG1;
    }
    fadeColor(this, 0, 0, this.currentbgRGB, linkBG2, .16, 0, 1);
    fadeColor(this.link, this.link.currentfgRGB, linkFG2, 0, 0, .16, 0, 1);
}

function highlightOut(){
    if(!this.currentbgRGB){
        return;
    }

    fadeColor(this, 0, 0, this.currentbgRGB, linkBG1, .3, 0, 1);
    fadeColor(this.link, this.link.currentfgRGB, linkFG1, 0, 0, .3, 0, 1);
}

function stretch(id, startSize, endSize, startPos, endPos, duration, delay, direction, animIdSuffix, end, power){
    var animId = id + 'Stretch' + animIdSuffix;
    stopAnim(animId);

    var element = $(id);
    if(!element){
        return false;
    }

    duration = duration || 1;
    delay = delay || 0;
    direction = direction || '';
    power = power || 2;

    var suffixWidth = '%';
    var suffixHeight = '%';
    var suffixX = '%';
    var suffixY = '%';

    if(typeof(endSize) == 'object'){
        if(startSize[0] != null && typeof(startSize[0]) == 'string' || endSize[0] != null && typeof(endSize[0]) == 'string'){
            suffixWidth = (typeof(endSize[0]) == 'string') ? endSize[0].replace(/[0-9]+/, '') : startSize[0].replace(/[0-9]+/, '');
            if(typeof(startSize[0]) == 'string'){
                startSize[0] = parseFloat(startSize[0]);
            }
            if(typeof(endSize[0]) == 'string'){
                endSize[0] = parseFloat(endSize[0]);
            }
        }
        if(startSize[1] != null && typeof(startSize[1]) == 'string' || endSize[1] != null && typeof(endSize[1]) == 'string'){
            suffixHeight = (typeof(endSize[1]) == 'string') ? endSize[1].replace(/[0-9]+/, '') : startSize[1].replace(/[0-9]+/, '');
            if(typeof(startSize[1]) == 'string'){
                startSize[1] = parseFloat(startSize[1].replace(/[^0-9]./, ''));
            }
            if(typeof(endSize[1]) == 'string'){
                endSize[1] = parseFloat(endSize[1].replace(/[^0-9]./, ''));
            }
        }
    }

    if(typeof(endPos) == 'object'){
        if(startPos[0] != null && typeof(startPos[0]) == 'string' || endPos[0] != null && typeof(endPos[0]) == 'string'){
            suffixX = (typeof(endPos[0]) == 'string') ? endPos[0].replace(/[0-9]+/, '') : startPos[0].replace(/[0-9]+/, '');
            if(typeof(startPos[0]) == 'string'){
                startPos[0] = parseFloat(startPos[0]);
            }
            if(typeof(endPos[0]) == 'string'){
                endPos[0] = parseFloat(endPos[0]);
            }
        }
        if(startPos[1] != null && typeof(startPos[1]) == 'string' || endPos[1] != null && typeof(endPos[1]) == 'string'){
            suffixY = (typeof(endPos[1]) == 'string') ? endPos[1].replace(/[0-9]+/, '') : startPos[1].replace(/[0-9]+/, '');
            if(typeof(startPos[1]) == 'string'){
                startPos[1] = parseFloat(startPos[1]);
            }
            if(typeof(endPos[1]) == 'string'){
                endPos[1] = parseFloat(endPos[1]);
            }
        }
    }

    var run = function(steps, step){
        if(typeof(startSize) == 'object'){
            if(startSize[0] != endSize[0]){
                element.style.width = easeInOut(startSize[0], endSize[0], steps, step, power, direction, true) + suffixWidth;
            }else if(endSize[0] != null){
                element.style.width = endSize[0] + suffixWidth;
            }

            if(startSize[1] != endSize[1]){
                element.style.height = easeInOut(startSize[1], endSize[1], steps, step, power, direction, true) + suffixHeight;
            }else if(endSize[0] != null){
                element.style.height = endSize[1] + suffixHeight;
            }

            if(element.style.display == 'none'){
                element.style.display = '';
            }
        }
        if(typeof(startPos) == 'object'){
            if(startPos[0] != endPos[0]){
                element.style.left = easeInOut(startPos[0], endPos[0], steps, step, power, direction, true) + suffixX;
            }else if(endPos[0] != null){
                element.style.left = endPos[0] + suffixX;
            }
            if(startPos[1] != endPos[1]){
                element.style.top = easeInOut(startPos[1], endPos[1], steps, step, power, direction, true) + suffixY;
            }else if(endPos[1] != null){
                element.style.top = endPos[1] + suffixY;
            }
        }
    };

    if(!end && endSize[0] == 0 && endSize[1] == 0){
        var end = function(){element.style.display = 'none';};
    }

    animate(animId, duration, delay, run, end);
}

function borderAnimate(id, startWidth, endWidth, startColor, endColor, duration, delay){
    var animId = id + 'borderAnim';
    stopAnim(animId);

    var element = $(id);
    if(!element){
        return false;
    }

    duration = duration || 1;

    delay = delay || 0;

    var run = function(steps, step){
        if(startWidth != endWidth){
            element.style.borderWidth = easeInOut(startWidth, endWidth, steps, step, 1, 'in', false) + 'px';
        }
        if(startColor != endColor){
            element.colorRGB = [
                easeInOut(startColor[0], startColor[0], steps, step, power, false),
                easeInOut(startColor[1], startColor[1], steps, step, power, false),
                easeInOut(startColor[2], startColor[2], steps, step, power, false)
                ];
            element.style.borderColor = "rgb("+
                element.colorRGB[0]+","+
                element.colorRGB[1]+","+
                element.colorRGB[2]+")";
        }
    };

    animate(animId, duration, delay, run);    
}

function fadeColor(elem, startfgRGB, endfgRGB, startbgRGB, endbgRGB, duration, delay, end){
//Color Fader with Memory by www.hesido.com, highly modified by Craig Laparo
    animId = elem.id + 'ColorFade';
    stopAnim(animId);

    var direction = 'in';
    var powr = 1;

    duration = duration || 1;
    delay = delay || 0;

    if(!startfgRGB){
        startfgRGB = elem.getStyle("color");
        if(startfgRGB.indexOf("rgb(") == 0){
            startfgRGB = startfgRGB.substr(4, startfgRGB.length - 5).split(", ");
        }else{
            startfgRGB = [255, 255, 255];
        }
    }
    if(!startbgRGB){
        startbgRGB = elem.getStyle("background-color");
        if(startbgRGB.indexOf("rgb(") == 0){
            startbgRGB = startbgRGB.substr(4, startbgRGB.length - 5).split(", ");
        }else{
            startbgRGB = [255, 255, 255];
        }
    }

    var run = function(steps, step){
        if(startfgRGB && endfgRGB && startfgRGB != endfgRGB){
            elem.currentfgRGB = [
                easeInOut(startfgRGB[0],endfgRGB[0],steps,step,powr,direction,false),
                easeInOut(startfgRGB[1],endfgRGB[1],steps,step,powr,direction,false),
                easeInOut(startfgRGB[2],endfgRGB[2],steps,step,powr,direction,false)
                ];
            elem.style.color = "rgb("+
                elem.currentfgRGB[0]+","+
                elem.currentfgRGB[1]+","+
                elem.currentfgRGB[2]+")";
        }
        if(startbgRGB && endbgRGB && startbgRGB != endbgRGB){
            elem.currentbgRGB = [
                easeInOut(startbgRGB[0],endbgRGB[0],steps,step,powr,direction,false),
                easeInOut(startbgRGB[1],endbgRGB[1],steps,step,powr,direction,false),
                easeInOut(startbgRGB[2],endbgRGB[2],steps,step,powr,direction,false)
                ];
            elem.style.backgroundColor = "rgb("+
                elem.currentbgRGB[0]+","+
                elem.currentbgRGB[1]+","+
                elem.currentbgRGB[2]+")";
        }
    };

    if(typeof(end) != 'function'){
        var end = null;
    }

    animate(animId, duration, delay, run, end);
}

function fade(id, max, duration, delay, end, animIdSuffix){
    var elem = $(id);
    if(!elem){
        return false;
    }

    if(!animIdSuffix){
        var animIdSuffix = '';
    }
    animId = id + 'Fade' + animIdSuffix;

    stopAnim(animId);

    duration = duration || 1;
    delay = delay || 0
    max = max || 0.0;

    if(max >= 1){
        max = 1.0;
    }

    max = parseFloat(max);

    var min = (elem.style.display == 'none') ? 0.0 : elem.getStyle("opacity") || 1.0;

    if(elem.style.display == 'none'){
        elem.setStyle({opacity: 0.0});
        elem.style.display = '';
    }
    
    var run = function(steps, step){elem.setStyle({opacity: eval(easeInOut(min, max, steps, step, 1, 'in', true))});}
    
    if(typeof(end) != 'function'){
        if(max == 0){
            var end = function(){elem.setStyle({display:'none'});};
        }else if(max == 1){
            var end = function(){elem.setStyle({opacity: ''});};
        }else{
            var end = null;
        }
    } 

    animate(animId, duration, delay, run, end);
}

/*function blink(id, blinks, duration, delay, end){
    var elem = $(id);
    if(!elem){
        return false;
    }

    blinks = blinks || 1;
    blinks++;
    duration = duration || .5;
    delay = delay || 0;

    animId = id + 'Blink';

    stopAnim(animId);
    var state = 1;

    var run = function(step, steps){
        if(step % Math.round(steps / (blinks)) == 0){
            state = 1 * (!state);
            elem.setStyle({opacity: state});
        }
    }

    if(typeof(end) != 'function'){
        var end = function(){return};
    }

    animate(animId, duration, delay, run, end);
}*/

function fold(id, duration, delay){
    var elem = $(id);
    if(!elem){
        return false;
    }

    duration = duration || 2;
    delay = delay || 0;

    if(!elem.initSize){
        getWinSize();

        var initWidth = (elem.style.width)? elem.style.width : (100 * elem.clientWidth / winView.width); 
        var initHeight = (elem.style.height)? elem.style.height : (100 * elem.clientHeight / winView.height);

        elem.initSize = [initWidth, initHeight];
    }

    stretch(id, [elem.initSize[0],elem.initSize[1]], [elem.initSize[0],0], 0, 0, (duration/2), delay, '', 'y');
    stretch(id, [elem.initSize[0],0], [0,0], 0, 0, (duration/2), (delay + duration/2), '', 'x');
}

function unfold(id, duration, delay){
    var elem = $(id);
    if(!elem){
        return false;
    }

    duration = duration || 2;
    delay = delay || 0;

    if(!elem.initSize){
        getWinSize();

        var initWidth = (elem.style.width)? elem.style.width : (100 * elem.clientWidth / winView.width); 
        var initHeight = (elem.style.height)? elem.style.height : (100 * elem.clientHeight / winView.height);

        elem.initSize = [initWidth, initHeight];
    }

    stretch(id, [0,0], [elem.initSize[0],0], 0, 0, (duration/2), delay, '', 'x');
    stretch(id, [elem.initSize[0],0], [elem.initSize[0],elem.initSize[1]], 0, 0, (duration/2), (delay + duration/2), '', 'y');
}

function getWinSize(){
    if(typeof(window.innerWidth) == 'number'){
        //Non-IE
        winView.width = window.innerWidth;
        winView.height = window.innerHeight;
    }else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)){
        //IE 6+ in 'standards compliant mode'
        winView.width = document.documentElement.clientWidth;
        winView.height = document.documentElement.clientHeight;
    }else if(document.body && (document.body.clientWidth || document.body.clientHeight)){
        //IE 4 compatible
        winView.width = document.body.clientWidth;
        winView.height = document.body.clientHeight;
    }
}
