/*----------------
Value circle
Raphael (SVG / VML) based interactive circle.
Dependencies: Raphael and Jquery
v 1.1 - 18.08.2011
----------------*/

function valueCircle (slices, buttons, debug) {
	var _this = this;
	
	
	_this.init = function () {
		initTooltip ();
		drawValueCircle();
		openAnimation();
	}
	
	function drawValueCircle () {
	
		/*----------------
			Init
		----------------*/
		
		var paper = Raphael("valueCircle", 430, 385);
		window.timers = {};
		
		/*----------------
			Public
		----------------*/
		
		_this.arrows = paper.set(); 
		_this.rotateCenter = "";
		_this.sliceLabels = [];
		_this.buttons = [];
		_this.cache_01 = "";
		_this.cache_02 = "";
		_this.titles = {}
		_this.shadow = ""
		
		
		/*----------------
		IE text adjustments
		----------------*/
		if (Raphael.vml) {
			for (var i=0;i<slices.length;i++){
			  slices[i].labelpos.y += 5;
			}
		}
	
		
		/*----------------
		PNGs (titles and shadow)
		----------------*/
		// The titles are done as PNG because there is no "text-on-path" on Raphael due to VML limitations
		// Embedding the paths would be considerably larger than using a PNG
		
		_this.titles.corp_finance = paper.image('/fileadmin/sys/images/value_circle/corporate_finance.png', 0, 67, 48, 217).hide();
		_this.titles.transactional = paper.image('/fileadmin/sys/images/value_circle/transactional.png', 124, 137, 18, 77).hide();
			
		_this.titles.man_consult = paper.image('/fileadmin/sys/images/value_circle/management_consulting.png', 352, 38, 73, 282).hide();
		_this.titles.organic = paper.image('/fileadmin/sys/images/value_circle/organic.png', 285, 157,  12, 44).hide();
	
		_this.shadow = paper.image('/fileadmin/sys/images/value_circle/shadow.png', 80, 295,  276, 99).hide();
		
		/*----------------
		Background circle 
		----------------*/
		 var circleCenter = [212, 178];
		 _this.rotateCenter = circleCenter;
		 var outerRadius = 175;
		 
		 var bgCircle = paper.circle (circleCenter[0],circleCenter[1], outerRadius) 
		 bgCircle.attr({'fill':'#fff','stroke-width':'2','stroke':'#d1d2d4','fill-opacity':'1','stroke-opacity':'1'});
		 bgCircle.toBack();
		 
		 var innerRadius1 = outerRadius - 70; // grey lines
		 var innerRadius2 = innerRadius1 - 14; // white lines
	
		
		/*----------------
		Colored arrows
		----------------*/
	
		// Blue arrow
		var shapes =[];	
		shapes[0]= paper.path(getArcSecgmentPath (170, 350, innerRadius2, innerRadius1)).attr({'fill':'#fff', 'stroke':'#f00'});	
		shapes[0].attr({'fill':'88-#FFFFFF:0-#076380:100','fill-opacity':'1', 'stroke-width':'1','stroke':'none','stroke-opacity':'1'});
		
		shapes[1]=paper.path('M 51.8 1.9 C 58.2 0.5 61.1 0 67.8 0 L 54.9 24 L 51.8 1.9');
		shapes[1].attr({'fill':'#036688','stroke-width':'1','stroke':'none','fill-opacity':'1','stroke-opacity':'1'});
		shapes[1].scale(1.52, 1.52, 0, 0);
		shapes[1].translate (113, 72);
			
		var blueArrow = paper.set();
		blueArrow.push(
			shapes[0],
			shapes[1]
		);
	
		// red arrow
		var redArrow = blueArrow.clone();
		redArrow[0].attr({'path' : getArcSecgmentPath (350, 170, innerRadius2, innerRadius1),'fill':'290-#FFFFFF:0-#D72328:100'});
		
		redArrow[1].attr({'path': 'M27.866,139.386c-6.422,1.041-9.346,1.392-16.1,1.03l14.169-23.267L27.866,139.386z', 'fill':'#D72328'});
		redArrow[1].scale(1.52, 1.52, 0, 0);
		redArrow[1].translate (188, 69);
	
		_this.arrows.push(blueArrow, redArrow);
		
	
		/*----------------
		Slices
		----------------*/
		
		 var greyLines = [];
		 var whiteLines = [];
		 var sliceBg = [];
	
		 
		 for (var i=0; i<slices.length;i++){	
			sliceBg[i] = drawSlice(i);
			_this.sliceLabels[i] = writeLabel(i).hide();
			greyLines[i] = drawSpoke(i, innerRadius1, outerRadius).attr({'stroke':'#d1d2d4'}).toFront();
			whiteLines[i] = drawSpoke(i, innerRadius2, innerRadius1).attr({'stroke':'#ffffff'});
		 }	
		 greyLines[0].toFront();
		
		
		/*----------------
		Buttons
		----------------*/
		
		var btnWidth = 120;
		var btnHeight = 16;
		var btnX = bgCircle.attrs.cx - btnWidth / 2;
		var btnBg = [];
		var btnLabels = [];
		
		for (var i=0;i<buttons.length;i++) {
			var btnY = (bgCircle.attrs.cy - 65) + ((btnHeight + 3) * i) ;
			btnBg[i] = createBtn (i, btnY)
			btnLabels[i] =  createBtnLabel (i, btnY);
			_this.buttons[i] = paper.set();
			_this.buttons[i].push(btnBg[i], btnLabels[i]);
			_this.buttons[i].hide();
		}
		
			
		/*----------------
		Cache for opening animation
		----------------*/
		 _this.cache_01 = getCache('left');
		 _this.cache_02 = getCache('right');
		 
		 redArrow[1].toFront();
		 blueArrow[1].toFront();
		 _this.shadow.toBack();
		 
	/*------------------------------------
		INNER FUNCTIONS
	-----------------------------------*/	
	
	 //Grey and white lines
		 function drawSpoke (sliceNr, radius1, radius2) {
			var theAngle = getRadAng(slices[sliceNr].angle);	
			var inner = getCoords (theAngle, radius1);
			var outer = getCoords (theAngle, radius2);
			return paper.path('M' + inner.x + ' ' + inner.y + 'L' + outer.x + ' ' + outer.y);
		}
		
		// Slice background
		function drawSlice (sliceNr) {
			var coords = [];
			var angle1 = slices[sliceNr].angle;
			var angle2 = sliceNr + 1 == slices.length ? slices[0].angle : slices[sliceNr+1].angle;
			
			var theSlice = paper.path(getArcSecgmentPath(angle1, angle2, innerRadius1, outerRadius)).attr({'fill':'#fff', 'stroke':'none'});
			theSlice.mouseover(getSliceRollover (sliceNr));
			theSlice.mouseout(getSliceRollout (sliceNr));
			theSlice.click(getSliceClick (sliceNr));
			
			if (debug) {
				var bbox = theSlice.getBBox();
				$('#debugSlicePos').append(sliceNr + ": " + Math.round(bbox.y) + " // ");
			}
			
			return theSlice
		}
		
			
		// Slice labels
		function writeLabel(sliceNr) {
			var theSlice = slices[sliceNr];
			var theLabel = paper.text(theSlice.labelpos.x,theSlice.labelpos.y,theSlice.label);
		
			var fontSize = theSlice.fontsize ? theSlice.fontsize : 11;
			theLabel.attr({"font-size" : fontSize, "font-family" : "'Lucida Sans Unicode', 'Lucida Grande', sans-serif"});
			
			theLabel.mouseover(getSliceRollover (sliceNr))
			theLabel.mouseout(getSliceRollout (sliceNr));
			theLabel.click(getSliceClick (sliceNr));
			if (debug) {
				var bbox = theLabel.getBBox();
				$('#debugLabelPos').append(sliceNr + ": " + Math.round(bbox.y) + " // ");
			}
			
			return theLabel;
		}
	
		function getSliceRollover(sliceNr) {
			return function () {
				if (window.timers['sl' + sliceNr]) {
					window.clearTimeout(window.timers['sl' + sliceNr]);
					delete window.timers['sl' + sliceNr];
				}
				
				sliceBg[sliceNr].attr({fill: "#eae9e8"});
				_this.sliceLabels[sliceNr].attr({"font-weight" : "bold"});
				document.body.style.cursor = 'pointer';
				showTooltip (slices[sliceNr].label, slices[sliceNr].text, "sl" + sliceNr);
			}	
		}
		
		function getSliceRollout(sliceNr) {
			return function () {
				// Stops mouseout event triggering on IE when going from the label to the slice background
				if (Raphael.vml) {
					window.timers['sl' + sliceNr]  = window.setTimeout(function () {doRollOut(sliceNr)}, 1);
				}
				else {
					doRollOut (sliceNr)
				}
	
				function doRollOut (sliceNr) {
					sliceBg[sliceNr].attr({fill: "#fff"});
					_this.sliceLabels[sliceNr].attr({"font-weight" : "normal"});
					document.body.style.cursor = 'default';
					hideTooltip();
				}
			}	
		}
		
		function getSliceClick (sliceNr) {
			return function () {
				showServiceLineContent(slices[sliceNr].linkref,250,0);
			}	
		}
		
		function createBtn (btnNr, btnY) {
			var theBtn = paper.rect(btnX, btnY, btnWidth, btnHeight, 10).attr({'stroke' : '#e0e0e0', 'fill': '90-#e9eaea-#fefefe'});	
			
			theBtn.mouseover(getBtnRollover(btnNr));
			theBtn.mouseout(getBtnRollout(btnNr));
			theBtn.click(getBtnClick (btnNr));
			
			return theBtn;
		}
		
		function createBtnLabel (btnNr, btnY){
			if (Raphael.vml) btnY += 5; //IE adjustment
			var theLabel = paper.text(btnX + (btnWidth / 2),btnY + (btnHeight / 2) + 3 ,buttons[btnNr].label);
			var fontSize = buttons[i].fontsize ? buttons[btnNr].fontsize : 10.5;
			theLabel.attr({"font-size" : fontSize, "font-family" : "'Lucida Sans Unicode', 'Lucida Grande', sans-serif", "color":"#565354"});
			
			theLabel.mouseover(getBtnRollover(btnNr));
			theLabel.mouseout(getBtnRollout(btnNr));
			theLabel.click(getBtnClick (btnNr));
			
			return theLabel;
		}
		
		function getBtnRollover(btnNr) {
			return function () {
				btnBg[btnNr].attr({'stroke' : '#e0e0e0', 'fill': '90-#cecfd1-#ececec'});
				btnLabels[btnNr].attr({"font-weight" : "bold"});
				document.body.style.cursor = 'pointer';
				showTooltip (buttons[btnNr].label, buttons[btnNr].text, "bt" + btnNr);
			}	
		}
		
		function getBtnRollout(btnNr) {
			return function () {
				btnBg[btnNr].attr({'stroke' : '#e0e0e0', 'fill': '90-#e9eaea-#fefefe'});
				btnLabels[btnNr].attr({"font-weight" : "normal"});
				document.body.style.cursor = 'nromal';
			}	
		}
		
		function getBtnClick (btnNr) {
			return function () {
				window.location = buttons[btnNr].link;
			}	
		}
		
	
	 function getCache (side) {
			var clipOrigin =  [bgCircle.attrs.cx, bgCircle.attrs.cy - outerRadius];
			
			if (side == 'left')  {
				clipOrigin[0] = bgCircle.attrs.cx - outerRadius - 3;
				arcSide = 1;
				clipWidth = outerRadius;
			}
			else {
				arcSide = 0;
				clipWidth = outerRadius + 3;
			}
				
			var thePath = "M " + bgCircle.attrs.cx + " " + clipOrigin[1];
			thePath +=    "L " + bgCircle.attrs.cx + " " + (clipOrigin[1] + (outerRadius * 2));
			thePath += 'A' + outerRadius + ',' + outerRadius + ' 0 0,' + arcSide + ' ' + bgCircle.attrs.cx + ' ' + clipOrigin[1];  
			thePath += "z";
			var theCache = paper.path(thePath);	
			theCache.attr({'fill':'#fff','stroke':'#fff', 'stroke-width': 3, 'clip-rect' : clipOrigin[0] + ' ' + (clipOrigin[1] - 3)  + ' ' + clipWidth + ' ' +  outerRadius * 2 + 6});
			return theCache;
		}
	
		
		/* 
		Helper functions
		*/
	
		// gets a segment of a "doughnut"
		function getArcSecgmentPath (angle1, angle2, innerRad, outerRad) {
			
			var coords = [];
			
			angle1 = getRadAng(angle1);
			angle2 = getRadAng(angle2);
		
			coords[0] = getCoords (angle1, innerRad);
			coords[1] = getCoords (angle1, outerRad);
			
			coords[2] = getCoords (angle2, outerRad);
			coords[3] = getCoords (angle2, innerRad);
			
			var pathText = 	'M' + coords[0].x + ' ' + coords[0].y;
			pathText += 'L' + coords[1].x + ' ' + coords[1].y;
			pathText += 'A' + outerRad + ',' + outerRad + ' 0 0,1 ' + coords[2].x + ' ' + coords[2].y;  
			pathText += 'L' + coords[3].x + ' ' + coords[3].y;
			pathText += 'A' + innerRad + ',' + innerRad + ' 0 0,0 ' + coords[0].x + ' ' + coords[0].y;  
			pathText += ' z';
			
			return pathText;	
		}
	
		// Returns angle in Radian starting from top of circle.
		function getRadAng (degAngle) {
			return Raphael.rad(degAngle - 90);
		}
		
		// Gets coordinates of the intersection of a circle and a spoke
		function getCoords (theAngle, radius) {
			var x =  (Math.cos(theAngle) * radius) +  circleCenter[0];
			var y =  (Math.sin(theAngle) * radius) +  circleCenter[1];
			return {'x' : x, 'y': y}
		}
	}
	
	
	/*----------------
	Open animation
	----------------*/
	
	function openAnimation () {
		var rotX =  _this.rotateCenter[0];
		var rotY =  _this.rotateCenter[1];
		
		var rotateDuration = 3000;
		
		var fadeInSpeed = 300;
		
		_this.arrows.rotate (-180, rotX, rotY);
			
		VMLSafeAnimate (_this.arrows, {"rotation" : "0 " + rotX + " " + rotY}, rotateDuration, ">", rotationEnd);
		VMLSafeAnimate (_this.cache_01, {"rotation" : "180 " + rotX + " " + rotY}, rotateDuration, ">");
		VMLSafeAnimate (_this.cache_02, {"rotation" : "180 " + rotX + " " + rotY}, rotateDuration, ">");
	
		function rotationEnd () {
			if (Raphael.vml) {// mouse event were not working on IE with a clip area set. Couldn't find a way to remove it altogether
				_this.cache_01.attr({'clip-rect' : '0 0 0 0'});
				_this.cache_02.attr({'clip-rect' : '0 0 0 0'});
			}		
					
			_this.cache_01.remove();
			_this.cache_02.remove();
			
			window.setTimeout(function () {showTitles();}, 500);
			window.setTimeout(function () {showLabels ();}, 2000);
			window.setTimeout(function () {showButtons ();}, 4000);
		}
		
		function showTitles(){
			FadeIn (_this.titles.corp_finance, true);
			FadeIn (_this.titles.man_consult, true);
			FadeIn (_this.titles.organic, true);
			FadeIn (_this.titles.transactional, true);
			FadeIn (_this.shadow, true);
		}
	
		function showButtons () {
			for (var i=0;i<_this.buttons.length;i++) {
				window.setTimeout(showButton(i), fadeInSpeed * i)
			}
		}
		
		function showLabels () {
			//Fade labels in for corporate finance and management consultants at the same time
			
			// Management consultants
			for (var i=0;i<6;i++) {
				window.setTimeout(showLabel(i), fadeInSpeed * i)
			}
			
			// Corporate finance
			for (var i=6;i<_this.sliceLabels.length;i++) {
				window.setTimeout(showLabel(i), fadeInSpeed * i - (6 * fadeInSpeed))
			}
			
		}
		
		function showButton(i) {
			return function (){FadeIn(_this.buttons[i]);}
		}
		
		function showLabel(i) {
			return function (){FadeIn(_this.sliceLabels[i]);}
		}
		
		function FadeIn (theItem, ieFix) {
			if (Raphael.vml && ieFix) {
				theItem.show();
			}
			else {
				theItem.attr({'opacity' : 0});
				theItem.show();
				theItem.animate({'opacity' : 1}, fadeInSpeed);	
			}

		}
		
		/*
			helper functions
		*/
		
		// Easing was buggy on IE, so we don't use it there
		function VMLSafeAnimate (theObject, Attr, duration, Easing, Callback) {
			Callback = Callback ? Callback : null;
			if (Raphael.vml) {
				theObject.animate (Attr, duration, Callback);
			}
			else {
				theObject.animate (Attr, duration, Easing, Callback);
			}
		}
	}
	
	/*----------------
	Tooltip
	----------------*/
	
	function initTooltip () {
	  $('body').append("<div id='toolTip'><div class='Top'>&nbsp;</div><div class='Middle'>&nbsp;</div><div class='Bottom'>&nbsp;</div></div>");
	  $(document).mousemove(function(e){
		  window.mouseXPos = e.pageX;
		  window.mouseYPos = e.pageY;
	   });	
	}
	
	function showTooltip (theTitle, theText, id) {
		var showDelay = 300;
		var fadeInSpeed = 200;
		
		showTooltip.tt = showTooltip.tt ? showTooltip.tt : $('#toolTip');
		showTooltip.ttcontents = showTooltip.ttcontents ? showTooltip.ttcontents : $('#toolTip .Middle');
		
		if (showTooltip.clearTimer) {
			window.clearTimeout(showTooltip.clearTimer);
			delete showTooltip.clearTimer;
		}
		
		if (showTooltip.current && showTooltip.current == id) {
			return;
		}
		else if (showTooltip.showTimer) {
			window.clearTimeout(showTooltip.showTimer);
			delete showTooltip.showTimer;
		}
		
		showTooltip.tt.hide();
		
		if (!theText) return;
		
		showTooltip.current = id;
		showTooltip.showTimer = window.setTimeout( _show, showDelay);
		
		function _show() {
			showTooltip.ttcontents.html("<h3>" + theTitle + "</h3>" + "<p>" + theText + "</p>");
			if (Raphael.vml) {//IE7 rendering bug with fade and PNG shadow
				showTooltip.tt.show();
			}
			else {
				showTooltip.tt.fadeIn(fadeInSpeed);
			}
			
			positionToolTip ();
		}	
	
		function positionToolTip () {
			showTooltip.tt.css('left',  window.mouseXPos - 50);
			showTooltip.tt.css('top',  window.mouseYPos + 30);
		}
	}
	
	function hideTooltip () {
		var hideDelay = 200;
		
		showTooltip.clearTimer = window.setTimeout( _hide, hideDelay);
		
		function _hide () {
			showTooltip.tt.hide();
			delete showTooltip.current;
		}
	}
	
}

	
valueCircle.version = "1.1";
