﻿fast.register("fadeTo", function( alpha, ondone ) {
	var self = this;
	var start = self.opacity();
	alpha = (typeof alpha == "undefined" ? 100 : alpha);
	var x = 0;
	for( var i = 1; i <= 10; i++ ) {		
		setTimeout( function() {
			x++;
			self.opacity( start + (((alpha-start)/10)*x) );
		}, i*20);
	};
	if( typeof ondone == "function" ) {
		setTimeout( ondone, 200 );
	};
	
	return this;
});

fast.register("fadeOut", function(cfg) {
	return this.fadeTo(0,cfg);
});

fast.register("fadeIn",function(cfg) {
	return this.fadeTo(100,cfg);
});

fast.register("moveBy", function( data ) {
    var self = this;
    var cfg = { top: -1, left: -1, ondone: null };
    for( attr in data ) { cfg[attr] = data[attr] };
    cfg.top += self.top();
    cfg.left += self.left();
    self.moveTo(cfg);
    return this;
}); 

fast.register("moveTo", function( data ) {
    var self = this;
    var cfg = { top: -1, left: -1, ondone: null };
    for( attr in data ) { cfg[attr] = data[attr] };
    var starty = self.top();
    var startx = self.left();
    var i = 0, j = 0;

    var tp = fast.extensions.calculateSmoothProgress(starty, 1, cfg.top);
    var lp = fast.extensions.calculateSmoothProgress(startx, 1, cfg.left);
    var mp = (tp.length > lp.length ? tp : lp);



    var done = function(iv) {
        clearInterval(iv);
        if (cfg.ondone) {
            var od = cfg.ondone;
            cfg.ondone = null;
            od();
        }
    };

    if (cfg.left >= 0 && startx != cfg.left) {
        var inter = setInterval(function() {
            if (i >= mp.length - 1) {
                done(inter);
            }
            var x = startx + ((cfg.left - startx) * mp[i].percent);
            self.left(x);
            i++;
        }, 10);
    };

    if (cfg.top >= 0 && starty != cfg.top) {
        var inter2 = setInterval(function() {
            if (j >= mp.length - 1) {
                done(inter2);
            }
            var y = starty + ((cfg.top - starty) * mp[j].percent);
            self.top(y);
            j++;
        }, 10);
    }
    
    return this;
}); 

fast.register("resizeBy", function( data ) {
	var self = this;
    var cfg = { width : -1, height : -1, ondone : null };
    for( attr in data ) { cfg[attr] = data[attr] };
    cfg.width += self.width();
    cfg.height += self.height();
    self.resizeTo(cfg);
    return this;
});

fast.register("resizeTo", function(data) {
    var self = this;
    var cfg = { width: -1, height: -1, valign: "left", align: "top", ondone: null };
    for (attr in data) { cfg[attr] = data[attr] };
    var startw = self.width();
    var starth = self.height();
    var startl = self.left();
    var startt = self.top();
    var i = 0, j = 0;

    var wp = fast.extensions.calculateSmoothProgress(startw, 1, cfg.width);
    var hp = fast.extensions.calculateSmoothProgress(starth, 1, cfg.height);
    var mp = (wp.length > hp.length ? wp : hp);

    var done = function(iv) {
        clearInterval(iv);
        if (cfg.ondone) {
            var od = cfg.ondone;
            cfg.ondone = null;
            od();
        }
    };

    if (cfg.width >= 0 && startw != cfg.width) {
        var inter = setInterval(function() {
            if (i >= mp.length - 1) {
                done(inter);
            }
            var w = startw + ((cfg.width - startw) * mp[i].percent);
            self.width(w);            
            if (cfg.align == "center") {
                self.left(startl - (w - startw) / 2);
            } else if (cfg.align == "right") {
                self.left(startl - (w - startw));
            };
            i++;
        }, 10);
    };

    if (cfg.height >= 0 && starth != cfg.height) {
        var inter2 = setInterval(function() {
            if (j >= mp.length - 1) {
                done(inter2);
            }
            var h = starth + ((cfg.height - starth) * mp[j].percent);
            self.height(h);
            if (cfg.valign == "center") {
                self.top(startt - (h - starth) / 2);
            } else if (cfg.valign == "bottom") {
                self.top(startt - (h - starth));
            };
            j++;
        }, 10);
    }

    return this;
});

fast.extend("calculateSmoothProgress", function(begin, speed, end) {

    var result = new Array();
    var progress = { begin: begin, speed: speed, end: end };

    var calc = function(arr) {

        arr.begin += arr.speed;
        if (arr.speed < 0) {
            if (arr.begin - arr.speed * (arr.speed - 1) / 2 < arr.end) {
                arr.speed++;
            } else if (arr.begin - (arr.speed - 1) * (arr.speed - 2) / 2 >= arr.end) {
                arr.speed--;
            }
        } else {
            if (arr.begin + arr.speed * (arr.speed + 1) / 2 > arr.end) {
                arr.speed--;
            } else if (arr.begin + (arr.speed + 1) * (arr.speed + 2) / 2 <= arr.end) {
                arr.speed++;
            }
        }
        return arr;
    };

    while (!(progress.begin == progress.end)) {
        progress = calc(progress);
        result.push({ percent: (progress.begin - begin) / (progress.end - begin), speed: progress.speed, end: progress.end });
    }

    return result;
});