/*
 * 	Plugin Name: WP Cirrus
 *	Plugin URI: http://ga-ap.de
 *	Description: A 3d javascript tagcloud inspired by WP Cumulus
 *	Version: 0.2
 *	Author: Christian Kramer & Hendrik Thole
 *	Author URI: http://www.ga-ap.de
 *	
 *	Copyright 2010, Christian Kramer & Hendrik Thole
 *	
 *	This file is part of WP-Cirrus Plugin.
 *	
 *	WP-Cirrus is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *   
 *	WP-Cirrus is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *   
 *	You should have received a copy of the GNU General Public License
 *	along with WP-Cirrus. If not, see <http://www.gnu.org/licenses/>.
 */


// globals
var cirr_offSetTheta = 0;
var cirr_offSetPhi = 0;
var cirr_offSetPsi = 0;
var cirrContainer;
var ySteps = 0.006;
var xSteps = 0.006;

// if the window is loaded
window.onload = function(){
	// get the main container
	cirrContainer = document.getElementById("cirrusCloud");
	
	// if no radius is given, determine one
	var radius = (parseInt(cirrContainer.style['height'])/3);
	if (typeof wpcirrusRadius != "undefined" && wpcirrusRadius != 0){
		radius = wpcirrusRadius;
	}
	
	// if no refreshrate is given use default
	var refreshRate = 30;
	if (typeof wpcirrusRefreshrate != "undefined" && wpcirrusRefreshrate != 0){
		refreshRate = wpcirrusRefreshrate;
	}

	// get the list items
	cirr_listItems = cirrContainer.getElementsByTagName("A");
	var itemLength = cirr_listItems.length-1;
	
	// for better positioning its neccessary to know the average height and width
	var heightOfAllItems = 0;
	var widthOfAllItems = 0;
	
	
	// theta -> 0 - pi
	// phi -> 0 - 2pi
	// compute sperical coordinates
	for (var i = 1; i <= cirr_listItems.length; i++){
		cirr_listItems[i-1].theta = new Number(Math.acos(-1+(2*i-1)/cirr_listItems.length)).toFixed(2);
		cirr_listItems[i-1].phi = new Number(Math.sqrt(cirr_listItems.length*Math.PI)*cirr_listItems[i-1].theta).toFixed(2);
		
			
		cirr_listItems[i-1].z = radius * Math.cos(cirr_listItems[i-1].theta);
		cirr_listItems[i-1].y = radius * Math.sin(cirr_listItems[i-1].theta) * Math.cos(cirr_listItems[i-1].phi);
		cirr_listItems[i-1].x = radius * Math.sin(cirr_listItems[i-1].theta) * Math.sin(cirr_listItems[i-1].phi);
		
		heightOfAllItems += cirr_listItems[i-1].offsetHeight;
		widthOfAllItems += cirr_listItems[i-1].offsetWidth;
			
		cirr_listItems[i-1].origFontSize = parseInt(cirr_listItems[i-1].style.fontSize);
		
	}

	// compute the average offsets
	var offsetTop = parseInt(cirrContainer.style['height'])/2 - heightOfAllItems/cirr_listItems.length/2;
	var offsetLeft = parseInt(cirrContainer.style['width'])/2 - widthOfAllItems/cirr_listItems.length/2;
	
	// start animating
	window.setInterval(function(){
		
		for(var i = 0; i < cirr_listItems.length; i++){
			
			var x, y, z;
			
			// some test of increase performance
			var sinThetacosPsi = Math.sin(cirr_offSetTheta)*Math.cos(cirr_offSetPsi);
			var sinThetasinPsi = Math.sin(cirr_offSetTheta)*Math.sin(cirr_offSetPsi);
			
			// rotatation matrix (LUT's are much slower)
			x = cirr_listItems[i].x * Math.cos(cirr_offSetTheta)*Math.cos(cirr_offSetPsi) + cirr_listItems[i].y * Math.cos(cirr_offSetTheta)*Math.sin(cirr_offSetPsi) - cirr_listItems[i].z * Math.sin(cirr_offSetTheta);  		
			y = cirr_listItems[i].x * (Math.sin(cirr_offSetPhi)*sinThetacosPsi-Math.cos(cirr_offSetPhi)*Math.sin(cirr_offSetPsi)) + cirr_listItems[i].y * (Math.sin(cirr_offSetPhi)*sinThetasinPsi+Math.cos(cirr_offSetPhi)*Math.cos(cirr_offSetPsi)) + cirr_listItems[i].z * Math.sin(cirr_offSetPhi)*Math.cos(cirr_offSetTheta);
			z = cirr_listItems[i].x * (Math.cos(cirr_offSetPhi)*sinThetacosPsi+Math.sin(cirr_offSetPhi)*Math.sin(cirr_offSetPsi)) + cirr_listItems[i].y * (Math.cos(cirr_offSetPhi)*sinThetasinPsi-Math.sin(cirr_offSetPhi)*Math.cos(cirr_offSetPsi)) + cirr_listItems[i].z * Math.cos(cirr_offSetPhi)*Math.cos(cirr_offSetTheta);

			// set coordinates
			cirr_listItems[i].style['top'] = z  + offsetTop + "px";
			cirr_listItems[i].style['left'] = y + offsetLeft + "px";
			
			// fontsize
			// TODO: need to make this cross browser
			cirr_listItems[i].style['fontSize'] = cirr_listItems[i].origFontSize + ((x/radius)*3) + "pt";
			
			// opacity
			// TODO: need to make this corss browser
			var opacity = 0.7+x/radius/3;
			cirr_listItems[i].style['opacity'] = opacity;
			cirr_listItems[i].style['-moz-opacity'] = opacity;
			cirr_listItems[i].style['-kthml-opacity'] = opacity;
			cirr_listItems[i].style['filter'] = "alpha(opacity=" + (opacity)*100+ ")";
			
			//z-index
			// TODO: need to make this cross browser
			var zIndex = Math.round(x+700);
			cirr_listItems[i].style['zIndex'] = zIndex;
			cirr_listItems[i].zIndex = zIndex;
			
//			
		}
		
		cirr_offSetTheta += ySteps;
//		cirr_offSetPhi += 0.004 ; 
		cirr_offSetPsi += xSteps;
		
		// instead of counting to infty reset the rotation angles
		if(cirr_offSetTheta > 2*Math.PI){
			cirr_offSetTheta = 0;
		}
//		if(cirr_offSetPhi > 2*Math.PI){
//			cirr_offSetPhi = 0;
//		}
		if(cirr_offSetPsi > 2*Math.PI){
			cirr_offSetPsi = 0;
		}
		
	}, refreshRate);
}

/*
 * tested in:
 * 
 * Safari 4.0.5
 * Firefox 3.6.3, 3.0.19
 * Chrome 5
 * Opera 9.64
 * IE 6, 8 
 */


