/* Animation(s) :D */

// Requires SN.Time.TimeManager
if (!SN.Time.TimeManager) {
	alert("SN.Time.Animation: This class requires SN.Time.TimeManager");
}

SN.Time.Animation = new Object();

SN.Time.Animation.Tween = function Tween(currentTarget, finalTarget, speed, onEnterFrame, onComplete) {
    var home = this;
    var paused = false;
    var eventWrapper = null;

    this.getFinalTarget = function() {
        return finalTarget;
    };

    this.setFinalTarget = function(newTarget) {
        finalTarget = newTarget;
        // If we change the finalTarget, let's start the animation again if need be.
        home.resume();
    };

    this.getCurrentTarget = function() {
        return currentTarget;
    };

    this.getSpeed = function() {
        return speed;
    };

    var inRange = function() {
        return (currentTarget <= (finalTarget + 1) && currentTarget >= (finalTarget - 1));
    };

    this.tween = function() {
        var increment = Math.round((finalTarget - currentTarget) / (speed / (20 / SN.Time.TimeManager.delay))); //(speed / (400 / (SN.Time.TimeManager.lowestDelay * SN.Time.TimeManager.lowestDelay))));
        return (currentTarget + ((finalTarget > currentTarget) ? Math.max(1, increment) : Math.min(-1, increment)));
    };

    var enterFrame = function enterFrame(e) {
        eventWrapper = e.obj
        // Here, we tween and check and deplay based on result!
        if (inRange()) {
            e['currentTarget'] = currentTarget = finalTarget;
            onEnterFrame(e);
            if (onComplete) {
                onComplete(e);
                if (!inRange()) {
                    // On complete we just restarted!
                    return;
                }
            }
            home.pause(); // Done listening
            return;
        }
        e['currentTarget'] = currentTarget = home.tween();
        onEnterFrame(e);
    };

    this.resume = function() {
        if (paused) {
            paused = false;
            SN.Time.TimeManager.addEventListener('onenterframe', enterFrame);
        }
    };

    this.pause = function() {
        if (!paused) {
            paused = true;
            SN.Time.TimeManager.removeEventListener('onenterframe', eventWrapper);
        }
    };

    var init = function() {
        // Calculate appropriate speed!
        speed = (((100 - Math.max(0, Math.min(100, speed))) / 100) * 48) + 2;
        paused = true;
        home.resume();
    };

    init();
};

SN.Time.Animation.Translate = function Translate(obj, axis, finalPos, onComplete, speed) {
    var home = this;
    this.inheritFrom = SN.Time.Animation.Tween;

    var stripPx = function(property) {
        try {
            return Number(property.split('px')[0]);
        } catch (e) {
            return 0;
        }
    };

    var init = function() {
        if (!speed) {
            speed = 95;
        }
        if (!onComplete) { // change this
            onComplete = function onDone(e) {
                //alert(e.time);
            };
        }
        if (axis == 'x') {
            home.inheritFrom(stripPx(obj.style.left), finalPos, speed, function everyFrame(e) {
                obj.style.left = e.currentTarget + "px";
            }, onComplete);
        } else if (axis == 'y') {
            home.inheritFrom(stripPx(obj.style.top), finalPos, speed, function everyFrame(e) {
                obj.style.top = e.currentTarget + "px";
            }, onComplete);
        } else {
            alert("SN.Time.Animation.Translate: Not a known axis (" + axis + ")");
        }
    };

    init();
};

SN.Time.Animation.Fade = function Fade(obj, finalOpac, onComplete, speed) {
    var home = this;
    this.inheritFrom = SN.Time.Animation.Tween;

    // FOR IE, we make a tweak to Tween to speed up the fades since IE isn't very good at them :(
    if (SN.Browser.isIE) {
        // override!!
        home.tween = function() {
            var increment = Math.round((home.getFinalTarget() - home.getCurrentTarget()) / (home.getSpeed() / (80 / SN.Time.TimeManager.delay))); //(speed / (400 / (SN.Time.TimeManager.lowestDelay * SN.Time.TimeManager.lowestDelay))));
            return (home.getCurrentTarget() + ((home.getFinalTarget() > home.getCurrentTarget()) ? Math.max(1, increment) : Math.min(-1, increment)));
        };
    }

    var init = function() {
        if (!speed) {
            speed = 95;
        }
        if (!onComplete) {
            onComplete = function onDone(e) {
                // Do nothing
            };
        }
        var opac = 50;
        if (SN.Browser.isIE) {
            try {
                opac = Number(obj.currentStyle['filter'].split('progid:DXImageTransform.Microsoft.Alpha(Opacity=')[1].split(')')[0]);
            } catch (e) {
                try {
                    opac = Number(obj.style.filter.split('progid:DXImageTransform.Microsoft.Alpha(Opacity=')[1].split(')')[0]);
                } catch (e) {
                    // Let it be 100!
                }
            }
            home.inheritFrom(opac, finalOpac, speed, function everyFrame(e) {
                obj.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(Opacity=' + e.currentTarget + ')';
            }, onComplete);
        } else {
            try {
                opac = document.defaultView.getComputedStyle(obj, null).getPropertyValue('opacity') * 100;
            } catch (e) {
                try {
                    opac = obj.style.opacity * 100;
                } catch (e) {
                    // Leave at 100!
                }
            }
            home.inheritFrom(opac, finalOpac, speed, function everyFrame(e) {
                obj.style.opacity = e.currentTarget / 100;
            }, onComplete);
        }
    };

    init();
};

SN.Time.Animation.Resize = function Resize(obj, axis, finalSize, onComplete, speed) {
	var home = this;
	this.inheritFrom = SN.Time.Animation.Tween;
	
	var init = function() {
		if (!speed) {
			speed = 95;
		}
		if (!onComplete) {
			onComplete = function onDone(e) {
				// Done!
			};
		}
		if (axis == 'x') {
			axis = 'clientWidth';
		} else if (axis == 'y') {
			axis = 'clientHeight';
		} else {
			alert("SN.Time.Animation.Resize: No such axis " + axis);
		}
		var initSize = obj[axis];
		axis = axis.split('client')[1].toLowerCase();
		home.inheritFrom(initSize, finalSize, speed, function everyFrame(e) {
			obj.style[axis] = e.currentTarget + 'px';
		}, onComplete);
	};
	
	init();
};

/* TODO: Rotate, scale, anything else? */
