var ax = 0, ay = 0;
var x,y,z,ux,ux2,uy,uy2,uz,uz2,uxy,uyz,uxz,newX,newY,newZ,id,angle,cosAngle,sinAngle,d,elem, elemStyle, realXRatio, realYratio, fontRatio;
var interval;
var isDecelerating = false;
$(document).ready(function(){
    initCloudArray();
    //bind the mouse movement to redefine the acceleration vector and start the rotation
	$('#tag_cloud').bind('mousemove', function(e){
        if(interval == null)
            interval = setInterval('rotateCloud()', 40); //each 40ms -> 25 FPS

        isDecelerating = false;
        ax = (e.pageX - $('#tag_cloud').offset().left) -  (containerWidth / 2);
		ay = (e.pageY - $('#tag_cloud').offset().top) -  (containerHeight / 2);

        computeAxis();
	});
    $('#tag_cloud').bind('mouseleave', function (e){ isDecelerating = true; });
});

function initCloudArray()
{
    computeAxis();
    $('#tag_cloud .point').each(function(){
        id = this.id;
        $('#'+id).css('marginLeft','-'+($('#'+id).width()/2)+'px');
        $('#'+id).css('marginTop','-'+($('#'+id).height()/2)+'px');
    });
    realXRatio = Math.round((containerWidth-(2*marge))/2);
    realYRatio = Math.round((containerHeight-(2*marge))/2);
    colorRRatio = Math.round((maximumRed-minimumRed)/2);
    colorGRatio = Math.round((maximumGreen-minimumGreen)/2);
    colorBRatio = Math.round((maximumBlue-minimumBlue)/2);
    fontRatio = (maximumFont-minimumFont)/2;
}
function computeAxis()
{
    d = Math.sqrt(ax * ax + ay * ay);
    angle = (Math.PI / 5000.0 * d); //with a speed factor
    c = Math.cos(angle);
    s = Math.sin(angle);
    ux = (ay / d);
    uy = (-ax / d);
    ux2 = ux * ux;
    uy2 = uy * uy;
    uxy = ux * uy;
}

function rotateCloud()
{
    if(isDecelerating)
    {
        ax = (ax * 0.8).toFixed(3);
        ay = (ay * 0.8).toFixed(3);
        computeAxis();
        if(ax == 0 && ay == 0)
        {
            clearInterval(interval);
            return;
        }
    }

    $('#tag_cloud .point').each(function(){
        id = this.id;
        x = cloudArray[id]['x'];
        y = cloudArray[id]['y'];
        z = cloudArray[id]['z'];
        newX = (x*(ux2+(1-ux2)*c) + y*(uxy*(1-c)) + z*(uy*s));
        newY = (x*(uxy*(1-c)) + y*(uy2+(1-uy2)*c) + z*(-ux*s));
        newZ = (x*(-uy*s) + y*(ux*s) + z*c);
        elemStyle = document.getElementById(id).style;
        elemStyle.left = getLeft(newX)+'px';
        elemStyle.top = getTop(newY)+'px';
        elemStyle.zIndex = getZIndex(newZ);
        elemStyle.fontSize = getFontSize(newZ)+'em';
        elemStyle.color = getRgbColor(newZ);
        cloudArray[id]['x'] = newX;
        cloudArray[id]['y'] = newY;
        cloudArray[id]['z'] = newZ;
    });
}

function getLeft(xVal)
{
    return Math.round((xVal + 1) * realXRatio + marge);
}

function getTop(yVal)
{
    return Math.round((yVal + 1) * realYRatio + marge);
}

function getRgbColor(zVal)
{
    var color = 'rgb(';
    color += Math.round((zVal + 1) * colorRRatio + minimumRed)+',';
    color += Math.round((zVal + 1) * colorGRatio + minimumGreen)+',';
    color += Math.round((zVal + 1) * colorBRatio + minimumBlue)+')';
    return color;
}

function getFontSize(zVal)
{
    return ((zVal + 1) * fontRatio + minimumFont).toFixed(2);
}

function getZIndex(zVal)
{
    return Math.round((zVal + 1) * 100);
}
