//////////////////////////////////////////////////////////////////////////////////////
// Powered by                                                                       //
//      __                                             __        __  _              //
//     / /___      ______        ____ ___  ____ ______/ /_____  / /_(_)___  ____ _  //
//    / //_/ | /| / / __ \______/ __ `__ \/ __ `/ ___/ //_/ _ \/ __/ / __ \/ __ `/  //
//   / ,<  | |/ |/ / /_/ /_____/ / / / / / /_/ / /  / ,< /  __/ /_/ / / / / /_/ /   //
//  /_/|_| |__/|__/ .___/     /_/ /_/ /_/\__,_/_/  /_/|_|\___/\__/_/_/ /_/\__, /    //
//               /_/                                                     /____/     //
//                                                                                  //
//                                                            13. August 2010  v1.1 //
//////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////
// Config                           //
//////////////////////////////////////

// Zeit zwischen jeder Animation (in Sekunden)
var timeBetweenAnimations = 0.2;

// Dauer jeder einzelnen Animation (in Sekunden)
var timeAnimationLength = 7;

// Zeit bis zur ersten Animation (-1 bedeutet keine Startanimation)
var timeToFirstAnimation = 0; // war: 3

// CSS der Schrift
var fontCSS = 'font-family:Arial; color: #000; opacity: 0.08;';

// CSS der Schrift im Highlight
var fontCSSHighlight = 'font-family:Arial; color: #F7F7F7; text-shadow: 0 0 12px #F7F7F7, 0 0 12px #F7F7F7;';

// CSS Zustand als Ziel der Animation (f�r Browser mit weniger Funktionen)
var fontCSSHighlightCompatibility = 'font-family:Arial; color: #DFDFDF;';

// Kann die Wolke auch innerhalb des Contents animieren?
var animateCloudWithinContent = false;

// Breite des Contents (der Bereich ohne Animation)
var contentWidth = 200;

// Minimale Schriftgroesse
var cloudFontSizeMinimum = 24;

// Maximale Groesse der Schrift
var cloudFontSizeMaximum = 48;

// Standart XML Datei, zum Lesen der Woerter aus der Wolke (um den Wert zu ueberschreiben cloudXMLFile im HTML benutzen)
var standardXMLFile = "content/xml/wolke.xml";

// Abstand der einzelnen Zeilen zu einander
var lineHight = 60;

// Anzahl der dar zu stellenden Spalten
var lines = 6;

// Debug Informationen anzeigen?
var showDebugInfo = true;

// Gleichzeitig aufleuchtende Elemente
var wolkeNumberOfElementsAtSameTime = 3;

// Zeit zwischen den einzelnen Elementen (in Sekunden)
var wolkeTimeBetweenElements = 1;

///////////////////////////////////////
// Ab hier nichts mehr veraendern!!! //
///////////////////////////////////////

/**
* Werte initialisieren
*
* cloudXMLFile => kann ueberschrieben werden durch Einbindung von JS Code in der Homepage
* cloudObjects => verwaltet die Woerter der Wolke, die aus der XML gelesen wurden
* version => Version des Browsers
* splitVersion => Teile der Version des Browsers
* animating => Zeigt an, ob die Animation der Cloud schon gestartet ist
* lastObject => Speichert die ID des zu letzt animierten Objektes an (verhindert das ein Element 2x hinter einander angezeigt wird)
*/
cloudXMLFile = "";
cloudObjects = new Array();
version = jQuery.browser.version || "0";
splitVersion = version.split('.');
animating = false;
lastObject = new Array();
lastLeft = 10000;
window.animateiCommsCloud = false;
window.generated = false;


/**
* Array Copy Funktion
*/
Array.prototype.copy = function() {
        return this.slice(0, this.length);
}

/**
* insertCloud()
*
* Fuegt den umrahmenden Div der Wolke als Grundgeruest in die Homepage
*/
function insertCloud() {
  if(!window.generated) {
  	window.generated = true;
  	height = (lineHight + 10) * lines;
  	// Breite der Cloud die erstellt werden soll
  	cloudWidth = 1400;

  	jQuery(".wolke").append('<div id="tagContainer" style="height:'+height+'px;width:890px;overflow:hidden;display:block; position: absolute;"><div id="cloud" style="width:'+cloudWidth+'px;height:100px;text-align:left;margin-left:-100px"></div></div>');
  	jQuery("#tagContainer").attr("hasLayout","true");
  	
  	generateRandomTexts();
  }
}

/**
* generateRandomTexts()
*
* liest aus der angegebenen XML Datei die Woerter der Wolke aus
*/
function generateRandomTexts() {
  cloudObjects = new Array(); // Array leeren, falls es nicht leer sein sollte
	jQuery.ajax({
		type: "GET",
		url: cloudXMLFile,
		dataType: "xml",
		success: function(xml) {
			jQuery(xml).find('a').each(function(){
				var name = jQuery(this).text();
				cloudObjects.push(name);
			});
	
			if(cloudObjects.length > 0) insertTags();
		}
	});
}

/**
* insertTag(tag)
* tag => String
*   Text des Inhaltes
*
* Fuegt ein neues div mit dem uebergebenen "tag" Inhalt in unsere Cloud ein
*/
function insertTag(tag) {
   size = Math.floor(Math.random()*(cloudFontSizeMaximum-cloudFontSizeMinimum)) + cloudFontSizeMinimum;
   jQuery("#cloud").append("<div class='cloudTags' style='float:left; margin-right:10px;height:"+lineHight+"px; display:table-cell;vertical-align:bottom;line-height:"+lineHight+"px;font-size:"+lineHight+"px;'><p class='cloudText1' style='position:relative; top:0px; left: 0px; font-size:"+size+"px; "+fontCSS+"'>"+tag+"</p></div>");
}

/**
* insertTags()
*
* fuellt das Cloud div mit Elementen
*/
function insertTags() {
  i = 0;
  j = 0;
  // Jeder Schleifendurchlauf fuegt einmal alle Elemente unserer verfuegbaren Texte in zufaelliger Reihenfolge in die Cloud
  while(i < lines + 1) {
	
    // Original Inhalt nicht anruehren...
    cloudSave = cloudObjects.copy();
  
    // So lange noch nicht verwendete Elemente existieren eines zufaellig aussuchen || Abbruch Element falls n�tig
    while(cloudSave.length > 0 && j < 1000 && i < lines + 1) {
      randomnumber = Math.floor(Math.random()*(cloudSave.length));
    
	  // Element zur Cloud hinzu fuegen
	  insertTag(cloudSave[randomnumber]);
	  
	  // Letztes Element in der Wolke
	  lastElement = jQuery(jQuery("#cloud").children()[jQuery("#cloud").children().size()-1]);
	  
	  // Wenn eine neue Zeile erreicht wurde, dann die Laufvariable hoch z�hlen
	  if(lastElement.offset().left < lastLeft) {
	    i++;
	  }
	  lastLeft = lastElement.offset().left;
    
	  // Dieses Element bereits als verwendet aus der Liste schmeissen
	  cloudSave.splice(randomnumber,1);
	  
	  j++;
	  //alert(lastElement.offset().left);
	  if(j >= 1000) {
	  	if(showDebugInfo) alert("Debug: Die Wolke konnte nicht erstellt werden, weil eine Endlosschleife erkannt wurde!");
	  	
	  	i = 500;
	  }
    }
	
	
	
	
  }
   //jQuery("#page_body").append("<div id='cloudError' style=position:relative;top:0px;left:0px;width:10px;height:10px;background:red;z-index:9999'></div>");
  
  jQuery(lastElement.remove());
  
  // im IE7 die Durchsichtigkeit korrigieren
  //if(jQuery.browser.msie && splitVersion[0] == 8) jQuery(".cloudText1").fadeTo(0, 0.12);
  if(jQuery.browser.msie) jQuery(".cloudText1").css("color","#737373");
  
  if(!animating) {
  	for(i = 0; i < wolkeNumberOfElementsAtSameTime; i++) {
  		if(i == 0) window.setTimeout(function() {firstAnimate();}, timeToFirstAnimation*1000+(wolkeTimeBetweenElements*i*1000));
		else window.setTimeout(function() {animateCloud();}, timeToFirstAnimation*1000+(wolkeTimeBetweenElements*i*1000));
	}
	animating = true;
  }
  //moveCloud(); // Nicht schoen zur Zeit...
}

/**
* firstAnimate()
*
* Wird bei der ersten Animation angezeigt
*/
function firstAnimate() {
  // Cloud einmal animieren
  animateCloud();
  // Ab dann in einem festen Intervall animieren =)
  
  for(i = 0; i < wolkeNumberOfElementsAtSameTime; i++) {
  	window.setInterval(function() {animateCloud();}, (timeBetweenAnimations+timeAnimationLength)*1000+ (wolkeTimeBetweenElements*i*1000));
  }
}

/**
* animateCloud()
*
* Waehlt aus dem Viewport des Browsers ein Wort aus, welches mit jQuery gehighlightet werden soll
*/
function animateCloud() {
  if(window.animateiCommsCloud) {
  // Nur animieren, wenn �berhaupt sichtbare Elemente vorhanden sind!
  	if(jQuery(window).width() > contentWidth) {
	  var max = jQuery("#cloud").children().length; // Anzahl der Elemente in unserer Cloud
	  var randomnumber = Math.floor(Math.random()*max); // Initialisierung einer Zufallszahl
	  
	  // Hier wird es kritisch! Nicht jedes Element in der Cloud ist auch wirklich sichtbar.
	  // Es muss berechnet werden, ob das Element passent zur Zufallszahl im Sichtbereich und
	  // ggf. falls eingestellt nicht vom Content verdeckt wird.
	  var numTry = 0;
	  while((
			 // Element befindet sich rechts ausserhalb des Bildschirmes
			 jQuery(jQuery("#cloud").children()[randomnumber]).offset().left + 20 > jQuery(window).width() || 
			 // Element befindet sich links ausserhalb des Bildschirmes
			 jQuery(jQuery("#cloud").children()[randomnumber]).offset().left+jQuery(jQuery("#cloud").children()[randomnumber]).width()-20 < 0 || (
			 // Element befindet sich im Verbotenen Bereich des Content
			 jQuery(jQuery("#cloud").children()[randomnumber]).offset().left+jQuery(jQuery("#cloud").children()[randomnumber]).width()-20 
																					< ((jQuery(window).width() / 2) + (contentWidth / 2)) &&
			 jQuery(jQuery("#cloud").children()[randomnumber]).offset().left+20 > ((jQuery(window).width() / 2) - (contentWidth / 2)) &&
			 // Soll dieser Verbotene Bereich beachtet werden?
			 !animateCloudWithinContent) ||
			 // Das Objekt wurde schon beim letzten Mal animiert... Will ich nicht!
			 lastObject.contains(randomnumber) ||
			 // Objekt liegt in der ersten Zeile...
			 jQuery(jQuery("#cloud").children()[randomnumber]).offset().top < 160) &&
			 numTry < 100000
		   ) {
			// So lange eine neue Zufallszahl bestimmen, bis keine Bedingung verletzt ist!	
			randomnumber = Math.floor(Math.random()*max);
			numTry++;
		}
	 if(numTry < 99999) {
	  lastObject.push(randomnumber);
	  
	  cssFont = fontCSSHighlight;
	  
	   // Inkompatible Browser nicht mit allen Animationen versehen 
	  if(jQuery.browser.msie && splitVersion[0] < 10) {
		  cssFont = fontCSSHighlightCompatibility;
	  }
		  //Abstand des Hintergrundes berechnen
		  var lineHightBG = lineHight + 10;
		  //lineHightBG = 0;
		  
		  // Text des animierten Divs
		  var tag = jQuery(jQuery("#cloud").children()[randomnumber]).find(".cloudText1").html();
		  
		  // FontSize auslesen
		  var size = jQuery(jQuery("#cloud").children()[randomnumber]).find(".cloudText1").css("font-size").replace("px", "");
		  
		  // Size
		  //var test123 = jQuery(jQuery("#cloud").children()[randomnumber]).find(".cloudText1").height();
		  //alert(test123);
		 
		  // Das Element fuer den Background Highlight einfuegen
		  if(!jQuery.browser.msie) jQuery(jQuery("#cloud").children()[randomnumber]).append("<p class='cloudText2' style='position:relative; display:none; margin-top:-"+lineHightBG+"px; margin-left: 0px; font-size:"+size+"px; "+cssFont+"'>"+tag+"</p>");
		  
	  // Animation Zeitverz�gert starten
	  window.setTimeout(function() {
	    if(jQuery.browser.msie) animateOneElementIE(randomnumber);
	    else animateOneElement(randomnumber);
	  }, 300); 
	  }
  }  
  }
}

/**
* animateOneElement()
* randomnumber => Index des zu animierenden Objektes
*
* Animiert ein Element in der Cloud
*/
function animateOneElement(randomnumber) { 
		  // animieren des Highlight im Hintergrund
		  jQuery(jQuery("#cloud").children()[randomnumber]).find(".cloudText2").fadeIn((timeAnimationLength / 2 * 1000), function() {
			  // Zurueck animieren
			  jQuery(jQuery("#cloud").children()[randomnumber]).find(".cloudText2").fadeOut((timeAnimationLength / 2 * 1000), function() {
				  // Hintergrund wieder entfernen (Garbage collection :D)
				  jQuery(jQuery("#cloud").children()[randomnumber]).find(".cloudText2").remove();
				  lastObject.remove(lastObject.indexOf(randomnumber));
			  });
		  });
}

function animateOneElementIE(randomnumber) { 
		  // animieren des Highlight im Hintergrund
		  jQuery(jQuery("#cloud").children()[randomnumber]).find(".cloudText1").animate({color: "#FFFFFF"},(timeAnimationLength / 2 * 1000), function() {
			  // Zurueck animieren
			  jQuery(jQuery("#cloud").children()[randomnumber]).find(".cloudText1").animate({color: "#737373"},
		  																				 (timeAnimationLength / 2 * 1000), function() {
				  // Hintergrund wieder entfernen (Garbage collection :D)
				  lastObject.remove(lastObject.indexOf(randomnumber));
			  });
			  
		  });
}

/**
* moveCloud()
* 
* Bewegt die Wolke in Richtung Links
*
* NICHT brauchbar
*/
function moveCloud() {  
  jQuery('#cloud').animate({
    marginLeft: '-4000px'
  }, {
    duration: 10000, 
    complete: function() {
      moveCloudBack();
    }
  });

}

/**
* moveCloudBack()
* 
* Bewegt die Wolke in Richtung Rechts
*
* NICHT brauchbar
*/
function moveCloudBack() {  
  jQuery('#cloud').animate({
    marginLeft: '4000px'
  }, {
    duration: 10000, 
    complete: function() {
      moveCloud();
    }
  });

}




	// Array Remove - By John Resig (MIT Licensed)
	Array.prototype.remove = function(from, to) {
  		var rest = this.slice((to || from) + 1 || this.length);
  		this.length = from < 0 ? this.length + from : from;
  		return this.push.apply(this, rest);
	};


	Array.prototype.indexOf = function(obj) {
     var i, idx = -1;
     for (i=0; i<this.length; i++) {
       if (this[i] === obj) {
         idx = i;
         break;
       }
     }
     return idx;
   };
   Array.prototype.lastIndexOf = function(obj) {
     this.reverse();
     var i, idx = -1;
     for (i=0; i<this.length; i++) {
       if (this[i] === obj) {
         idx = (this.length - 1 - i);
         break;
       }
     }
     this.reverse();
     return idx;
   };

   Array.prototype.contains = function(obj) {
     var i, listed = false;
     for (i=0; i<this.length; i++) {
       if (this[i] === obj) {
         listed = true;
         break;
       }
     }
     return listed;
   };


(function(jQuery){

	// We override the animation for all of these color styles
	jQuery.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){
		jQuery.fx.step[attr] = function(fx){
			if ( fx.state == 0 ) {
				fx.start = getColor( fx.elem, attr );
				fx.end = getRGB( fx.end );
			}

			if(!fx.elem.style[attr]) alert('fx.elem.style[attr] nicht da');
			//if(!fx.elem.style) alert('fx.elem.style nicht da');
			//if(!fx.elem.) alert('fx.elem nicht da');
			//if(!fx) alert('fx nicht da');
try {

			fx.elem.style[attr] = "rgb(" + 
				Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0) + "," + 
				Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0) + "," +
				Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0) + "," +
				")";
}
catch (e) 
{
/*

$(fx.elem).attr({color:'red'}); 
$("#content").hide();
$("#cloudError").attr({left:$(fx.elem).offset().left, top:$(fx.elem).offset().top});
alert
	(
	'Fehler:'	+	
	' pos: ' + fx.pos +
	' elem: ' + $(fx.elem).html() + 
	' elem.left: ' + $(fx.elem).offset().left + 
	' elem.top: ' + $(fx.elem).offset().top + 
	''
	)
$("#content").show();
				*/
}				
/*
			fx.elem.style[attr] = "rgb(" + [
				Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0),
				Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0),
				Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0)
			].join(",") + ")";
*/
		}
	});

	// Color Conversion functions from highlightFade
	// By Blair Mitchelmore
	// http://jquery.offput.ca/highlightFade/

	// Parse strings looking for color tuples [255,255,255]
	function getRGB(color) {
		var result;

		// Check if we're already dealing with an array of colors
		if ( color && color.constructor == Array && color.length == 3 )
			return color;

		// Look for rgb(num,num,num)
		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
			return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])];

		// Look for rgb(num%,num%,num%)
		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
			return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];

		// Look for #a0b1c2
		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
			return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];

		// Look for #fff
		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
			return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];

		// Otherwise, we're most likely dealing with a named color
		return colors[jQuery.trim(color).toLowerCase()];
	}
	
	function getColor(elem, attr) {
		var color;

		do {
			color = jQuery.curCSS(elem, attr);

			// Keep going until we find an element that has color, or we hit the body
			if ( color != '' && color != 'transparent' || jQuery.nodeName(elem, "body") )
				break; 

			attr = "backgroundColor";
		} while ( elem = elem.parentNode );

		return getRGB(color);
	};
	
	// Some named colors to work with
	// From Interface by Stefan Petre
	// http://interface.eyecon.ro/

	var colors = {
		aqua:[0,255,255],
		azure:[240,255,255],
		beige:[245,245,220],
		black:[0,0,0],
		blue:[0,0,255],
		brown:[165,42,42],
		cyan:[0,255,255],
		darkblue:[0,0,139],
		darkcyan:[0,139,139],
		darkgrey:[169,169,169],
		darkgreen:[0,100,0],
		darkkhaki:[189,183,107],
		darkmagenta:[139,0,139],
		darkolivegreen:[85,107,47],
		darkorange:[255,140,0],
		darkorchid:[153,50,204],
		darkred:[139,0,0],
		darksalmon:[233,150,122],
		darkviolet:[148,0,211],
		fuchsia:[255,0,255],
		gold:[255,215,0],
		green:[0,128,0],
		indigo:[75,0,130],
		khaki:[240,230,140],
		lightblue:[173,216,230],
		lightcyan:[224,255,255],
		lightgreen:[144,238,144],
		lightgrey:[211,211,211],
		lightpink:[255,182,193],
		lightyellow:[255,255,224],
		lime:[0,255,0],
		magenta:[255,0,255],
		maroon:[128,0,0],
		navy:[0,0,128],
		olive:[128,128,0],
		orange:[255,165,0],
		pink:[255,192,203],
		purple:[128,0,128],
		violet:[128,0,128],
		red:[255,0,0],
		silver:[192,192,192],
		white:[255,255,255],
		yellow:[255,255,0]
	};
	
})(jQuery);
