/**
 * a javascript run tagCloud
 * insert a list of <li> and provide the id of the relevant <ul>
 *
 */

function tagCloud()
{
	/* Setting option defaults */
	this.defaults = {
		element: "tagcloud",
		innerElement: "li"
	};

	/* Closure for this */
	var thisObject = this;

	/* starting zIndex for list elements */
	thisObject.startingZindex = 100;
	thisObject.busy = false;

	this.init = function(element) {
		/* recupera tutti gli oggetti e li dispone in una sfera, modificando opacity e dimensione */
		thisObject.canvas = $(element);
		thisObject.clouds = $$("#" + element + " li");
		thisObject.defaultHeight = 10;
		thisObject.keepAnimation = 10;
		thisObject.speed = 0;
		thisObject.angle = 0;
		thisObject.maxItems = 16;
		thisObject.offsetLeft = thisObject.canvas.cumulativeOffset()["left"];
		thisObject.offsettop = thisObject.canvas.cumulativeOffset()["top"];
		thisObject.tagWidth = thisObject.canvas.getWidth();
		thisObject.tagHeight = thisObject.canvas.getHeight();
		thisObject.radius = Math.min(thisObject.tagHeight / 2, thisObject.tagWidth / 2);
		thisObject.positions = new Array();
		for (i = 1; i <= thisObject.clouds.length; i++) {
			thisObject.clouds[i-1].absolutize();
			phi = Math.acos(-1.0 + (2.0 * i - 1.0) / thisObject.clouds.length);
			theta = Math.sqrt(thisObject.clouds.length * Math.PI) * phi;
			x = Math.cos(theta) * Math.sin(phi);
			y = Math.sin(theta) * Math.sin(phi);
			z = Math.cos(phi);
			thisObject.positions[i] = {"x": x, "y": y, "z": z};
		}

		thisObject.draw3D(0, 0);
		thisObject.canvas.observe('mousemove', this.changeSpeed);
		thisObject.canvas.observe('mouseover', this.startanimation);
		thisObject.canvas.observe('mouseout', this.stopanimation);
	};

	this.startanimation = function(event) {
		thisObject.keepAnimation = 10;
		if (!thisObject.busy) {
			thisObject.busy = true;
			thisObject.refresh();
		}
	}

	this.changeSpeed = function(event) {
		thisObject.keepAnimation = 10;
		thisObject.dx = (Event.pointerX(event) - thisObject.offsetLeft - thisObject.tagWidth / 2) / (thisObject.tagWidth / 2);
		thisObject.dy = (thisObject.tagHeight / 2 - (Event.pointerY(event) - thisObject.offsettop)) / (thisObject.tagHeight / 2);

		thisObject.speed = Math.sqrt(Math.pow(thisObject.dx, 2) + Math.pow(thisObject.dy, 2)) / 17;
		//if (Math.abs(thisObject.dx) < 10) thisObject.dx = 0;
		//if (Math.abs(thisObject.dy) < 10) thisObject.dy = 0;
		thisObject.vectorX = thisObject.dx;
		thisObject.vectorY = thisObject.dy;
	}

	this.stopanimation=function(event) {
		thisObject.keepAnimation--;
		if (thisObject.keepAnimation == 0) {
			thisObject.busy = false;
		}
	}

	this.draw3D = function() {
		max = thisObject.clouds.length;
		offset = 2 * Math.PI / max;
		r = thisObject.radius;
		a = thisObject.angle;

		//lat = Math.acos(thisObject.dy) - Math.PI/2;
		//lng = Math.atan2(thisObject.dx, thisObject.dy);
		lat = Math.acos(0.5) - Math.PI / 2;
		lng = Math.atan2(0.5, 0.5);

		vy = Math.cos(lat);
		vz = Math.sqrt(Math.pow((1- Math.sin(lng) - Math.cos(lat) * Math.cos(lng)), 2));
		vx = Math.sin(lat);
		
		for (i = 1; i < max + 1; i++) {
			oldx = r * thisObject.positions[i]["x"];
			oldy = r * thisObject.positions[i]["y"];
			oldz = r * thisObject.positions[i]["z"];

			x = oldx * (1 + (1 - Math.cos(a)) * (vx * vx - 1)) +
				oldy * ((1 - Math.cos(a)) * vx * vy) +
				oldz * (vy * Math.sin(a) + (1 - Math.cos(a)) * vx * vz);
			y = oldx * (vz * (Math.sin(a) + (1 - Math.cos(a)) * vx * vy)) +
				oldy * (1 + (1 - Math.cos(a)) * (vy * vy - 1)) +
				oldz * (vx * Math.sin(a) + (1 - Math.cos(a) * vy * vz));
			z = oldx * (-vy * Math.sin(a) + (1 - Math.cos(a)) * vx * vz) +
				oldy * (vx * Math.sin(a) + (1 - Math.cos(a)) * vy * vz) +
				oldz * (1 + (1 - Math.cos(a)) * (vz * vz - 1));

			z = 100 - Math.max(10, (z / r * 100));
			
			newHeight = Math.floor(thisObject.defaultHeight + (thisObject.defaultHeight / 100) * z) * 0.85;
	 		thisObject.clouds[i-1]. setStyle({
	 			fontSize: newHeight + "px",
		 		height: (newHeight + 4) + "px",
		 		left: Math.floor(thisObject.tagWidth / 2 + x - thisObject.clouds[i-1].getWidth() / 2.1) + "px",
				top: Math.floor(2 + (thisObject.tagWidth / 1.61) * (i - 1) / max - 23 * (i - 1) + y / max) + "px",
				opacity: z / 100
	 		});
		}
	}

	this.refresh = function() {
		if (thisObject.busy && thisObject.keepAnimation > 0) {
			thisObject.maxItems = thisObject.clouds.length;
			duePi = Math.PI * 2;
			if ((thisObject.dx * thisObject.dy) > 0)
				thisObject.angle += (thisObject.speed / 10) * thisObject.keepAnimation;
			else
				thisObject.angle -= (thisObject.speed / 10) * thisObject.keepAnimation;
			if (thisObject.angle > 2 * Math.PI)
				thisObject.angle -= 2 * Math.PI;
			if (thisObject.angle < -2 * Math.PI)
				thisObject.angle += 2 * Math.PI;

			thisObject.draw3D();

			if (thisObject.keepAnimation < 10) {
				thisObject.keepAnimation--;
			}
			if (thisObject.keepAnimation == 0)
				thisObject.busy = false
			window.setTimeout(thisObject.refresh, 50);
		}
	}
}
