/*
Flot plugin for rendering pie charts. The plugin assumes the data is 
coming is as a single data value for each series, and each of those 
values is a positive value or zero (negative numbers don't make 
any sense and will cause strange effects). The data values do 
NOT need to be passed in as percentage values because it 
internally calculates the total and percentages.

* Created by Brian Medendorp, June 2009
* Updated November 2009 with contributions from: btburnett3, Anthony Aragues and Xavi Ivars

* Changes:
	2009-10-22: lineJoin set to round
	2009-10-23: IE full circle fix, donut
	2009-11-11: Added basic hover from btburnett3 - does not work in IE, and center is off in Chrome and Opera
	2009-11-17: Added IE hover capability submitted by Anthony Aragues
	2009-11-18: Added bug fix submitted by Xavi Ivars (issues with arrays when other JS libraries are included as well)
		

Available options are:
series: {
	pie: {
		show: true/false
		radius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto'
		innerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect
		startAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result
		tilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show)
		offset: {
			top: integer value to move the pie up or down
			left: integer value to move the pie left or right, or 'auto'
		},
		stroke: {
			color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF')
			width: integer pixel width of the stroke
		},
		label: {
			show: true/false, or 'auto'
			formatter:  a user-defined function that modifies the text/style of the label text
			radius: 0-1 for percentage of fullsize, or a specified pixel length
			background: {
				color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000')
				opacity: 0-1
			},
			threshold: 0-1 for the percentage value at which to hide labels (if they're too small)
		},
		combine: {
			threshold: 0-1 for the percentage value at which to combine slices (if they're too small)
			color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined
			label: any text value of what the combined slice should be labeled
		}
		highlight: {
			opacity: 0-1
		}
	}
}

More detail and specific examples can be found in the included HTML file.

*/

(function ($) 
{
	function init(plot) // this is the "body" of the plugin
	{
		var canvas = null;
		var target = null;
		var maxRadius = null;
		var centerLeft = null;
		var centerTop = null;
		var total = 0;
		var redraw = true;
		var redrawAttempts = 10;
		var shrink = 0.95;
		var legendWidth = 0;
		var processed = false;
		var raw = false;
		
		// interactive variables	
		var highlights = [];	
	
		// add hook to determine if pie plugin in enabled, and then perform necessary operations
		plot.hooks.processOptions.push(checkPieEnabled);
		plot.hooks.bindEvents.push(bindEvents);	

		// check to see if the pie plugin is enabled
		function checkPieEnabled(plot, options)
		{
			if (options.series.pie.show)
			{
				//disable grid
				options.grid.show = false;
				
				// set labels.show
				if (options.series.pie.label.show=='auto')
					if (options.legend.show)
						options.series.pie.label.show = false;
					else
						options.series.pie.label.show = true;
				
				// set radius
				if (options.series.pie.radius=='auto')
					if (options.series.pie.label.show)
						options.series.pie.radius = 3/4;
					else
						options.series.pie.radius = 1;
						
				// ensure sane tilt
				if (options.series.pie.tilt>1)
					options.series.pie.tilt=1;
				if (options.series.pie.tilt<0)
					options.series.pie.tilt=0;
			
				// add processData hook to do transformations on the data
				plot.hooks.processDatapoints.push(processDatapoints);
				plot.hooks.drawOverlay.push(drawOverlay);	
				
				// add draw hook
				plot.hooks.draw.push(draw);
			}
		}
	
		// bind hoverable events
		function bindEvents(plot, eventHolder) 		
		{		
			var options = plot.getOptions();
			
			if (options.series.pie.show && options.grid.hoverable)
				eventHolder.unbind('mousemove').mousemove(onMouseMove);
				
			if (options.series.pie.show && options.grid.clickable)
				eventHolder.unbind('click').click(onClick);
		}	
		

		// debugging function that prints out an object
		function alertObject(obj)
		{
			var msg = '';
			function traverse(obj, depth)
			{
				if (!depth)
					depth = 0;
				for (var i = 0; i < obj.length; ++i)
				{
					for (var j=0; j<depth; j++)
						msg += '\t';
				
					if( typeof obj[i] == "object")
					{	// its an object
						msg += ''+i+':\n';
						traverse(obj[i], depth+1);
					}
					else
					{	// its a value
						msg += ''+i+': '+obj[i]+'\n';
					}
				}
			}
			traverse(obj);
			alert(msg);
		}
		
		function calcTotal(data)
		{
			for (var i = 0; i < data.length; ++i)
			{
				var item = parseFloat(data[i].data[0][1]);
				if (item)
					total += item;
			}
		}	
		
		function processDatapoints(plot, series, data, datapoints) 
		{	
			if (!processed)
			{
				processed = true;
			
				canvas = plot.getCanvas();
				target = $(canvas).parent();
				options = plot.getOptions();
			
				plot.setData(combine(plot.getData()));
			}
		}
		
		function setupPie()
		{
			legendWidth = target.children().filter('.legend').children().width();
		
			// calculate maximum radius and center point
			maxRadius =  Math.min(canvas.width,(canvas.height/options.series.pie.tilt))/2;
			centerTop = (canvas.height/2)+options.series.pie.offset.top;
			centerLeft = (canvas.width/2);
			
			if (options.series.pie.offset.left=='auto')
				if (options.legend.position.match('w'))
					centerLeft += legendWidth/2;
				else
					centerLeft -= legendWidth/2;
			else
				centerLeft += options.series.pie.offset.left;
					
			if (centerLeft<maxRadius)
				centerLeft = maxRadius;
			else if (centerLeft>canvas.width-maxRadius)
				centerLeft = canvas.width-maxRadius;
		}
		
		function fixData(data)
		{
			for (var i = 0; i < data.length; ++i)
			{
				if (typeof(data[i].data)=='number')
					data[i].data = [[1,data[i].data]];
				else if (typeof(data[i].data)=='undefined' || typeof(data[i].data[0])=='undefined')
				{
					if (typeof(data[i].data)!='undefined' && typeof(data[i].data.label)!='undefined')
						data[i].label = data[i].data.label; // fix weirdness coming from flot
					data[i].data = [[1,0]];
					
				}
			}
			return data;
		}
		
		function combine(data)
		{
			data = fixData(data);
			calcTotal(data);
			var combined = 0;
			var numCombined = 0;
			var color = options.series.pie.combine.color;
			
			var newdata = [];
			for (var i = 0; i < data.length; ++i)
			{
				// make sure its a number
				data[i].data[0][1] = parseFloat(data[i].data[0][1]);
				if (!data[i].data[0][1])
					data[i].data[0][1] = 0;
					
				if (data[i].data[0][1]/total<=options.series.pie.combine.threshold)
				{
					combined += data[i].data[0][1];
					numCombined++;
					if (!color)
						color = data[i].color;
				}				
				else
				{
					newdata.push({
						data: [[1,data[i].data[0][1]]], 
						color: data[i].color, 
						label: data[i].label,
						angle: (data[i].data[0][1]*(Math.PI*2))/total,
						percent: (data[i].data[0][1]/total*100)
					});
				}
			}
			if (numCombined>0)
				newdata.push({
					data: [[1,combined]], 
					color: color, 
					label: options.series.pie.combine.label,
					angle: (combined*(Math.PI*2))/total,
					percent: (combined/total*100)
				});
			return newdata;
		}		
		
		function draw(plot, newCtx)
		{
			if (!target) return; // if no series were passed
			ctx = newCtx;
		
			setupPie();
			var slices = plot.getData();
		
			var attempts = 0;
			while (redraw && attempts<redrawAttempts)
			{
				redraw = false;
				if (attempts>0)
					maxRadius *= shrink;
				attempts += 1;
				clear();
				if (options.series.pie.tilt<=0.8)
					drawShadow();
				drawPie();
			}
			if (attempts >= redrawAttempts) {
				clear();
				target.prepend('<div class="error">Could not draw pie with labels contained inside canvas</div>');
			}
			
			if ( plot.setSeries && plot.insertLegend )
			{
				plot.setSeries(slices);
				plot.insertLegend();
			}
			
			// we're actually done at this point, just defining internal functions at this point
			
			function clear()
			{
				ctx.clearRect(0,0,canvas.width,canvas.height);
				target.children().filter('.pieLabel, .pieLabelBackground').remove();
			}
			
			function drawShadow()
			{
				var shadowLeft = 5;
				var shadowTop = 15;
				var edge = 10;
				var alpha = 0.02;
			
				// set radius
				if (options.series.pie.radius>1)
					var radius = options.series.pie.radius;
				else
					var radius = maxRadius * options.series.pie.radius;
					
				if (radius>=(canvas.width/2)-shadowLeft || radius*options.series.pie.tilt>=(canvas.height/2)-shadowTop || radius<=edge)
					return;	// shadow would be outside canvas, so don't draw it
			
				ctx.save();
				ctx.translate(shadowLeft,shadowTop);
				ctx.globalAlpha = alpha;
				ctx.fillStyle = '#000';

				// center and rotate to starting position
				ctx.translate(centerLeft,centerTop);
				ctx.scale(1, options.series.pie.tilt);
				
				//radius -= edge;
				for (var i=1; i<=edge; i++)
				{
					ctx.beginPath();
					ctx.arc(0,0,radius,0,Math.PI*2,false);
					ctx.fill();
					radius -= i;
				}	
				
				ctx.restore();
			}
			
			function drawPie()
			{
				startAngle = Math.PI*options.series.pie.startAngle;
				
				// set radius
				if (options.series.pie.radius>1)
					var radius = options.series.pie.radius;
				else
					var radius = maxRadius * options.series.pie.radius;
				
				// center and rotate to starting position
				ctx.save();
				ctx.translate(centerLeft,centerTop);
				ctx.scale(1, options.series.pie.tilt);
				//ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera
				
				// draw slices
				ctx.save();
				var currentAngle = startAngle;
				for (var i = 0; i < slices.length; ++i)
				{
					slices[i].startAngle = currentAngle;
					drawSlice(slices[i].angle, slices[i].color, true);
				}
				ctx.restore();
				
				// draw slice outlines
				ctx.save();
				ctx.lineWidth = options.series.pie.stroke.width;
				currentAngle = startAngle;
				for (var i = 0; i < slices.length; ++i)
					drawSlice(slices[i].angle, options.series.pie.stroke.color, false);
				ctx.restore();
					
				// draw donut hole
				drawDonutHole(ctx);
				
				// draw labels
				if (options.series.pie.label.show)
					drawLabels();
				
				// restore to original state
				ctx.restore();
				
				function drawSlice(angle, color, fill)
				{	
					if (angle<=0)
						return;
				
					if (fill)
						ctx.fillStyle = color;
					else
					{
						ctx.strokeStyle = color;
						ctx.lineJoin = 'round';
					}
						
					ctx.beginPath();
					if (Math.abs(angle - Math.PI*2) > 0.000000001)
						ctx.moveTo(0,0); // Center of the pie
					else if ($.browser.msie)
						angle -= 0.0001;
					//ctx.arc(0,0,radius,0,angle,false); // This doesn't work properly in Opera
					ctx.arc(0,0,radius,currentAngle,currentAngle+angle,false);
					ctx.closePath();
					//ctx.rotate(angle); // This doesn't work properly in Opera
					currentAngle += angle;
					
					if (fill)
						ctx.fill();
					else
						ctx.stroke();
				}
				
				function drawLabels()
				{
					var currentAngle = startAngle;
					
					// set radius
					if (options.series.pie.label.radius>1)
						var radius = options.series.pie.label.radius;
					else
						var radius = maxRadius * options.series.pie.label.radius;
					
					for (var i = 0; i < slices.length; ++i)
					{
						if (slices[i].percent >= options.series.pie.label.threshold*100)
							drawLabel(slices[i], currentAngle, i);
						currentAngle += slices[i].angle;
					}
					
					function drawLabel(slice, startAngle, index)
					{
						if (slice.data[0][1]==0)
							return;
							
						// format label text
						var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter;
						if (lf)
							text = lf(slice.label, slice);
						else
							text = slice.label;
						if (plf)
							text = plf(text, slice);
							
						var halfAngle = ((startAngle+slice.angle) + startAngle)/2;
						var x = centerLeft + Math.round(Math.cos(halfAngle) * radius);
						var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt;
						
						var html = '<span class="pieLabel" id="pieLabel'+index+'" style="position:absolute;top:' + y + 'px;left:' + x + 'px;">' + text + "</span>";
						target.append(html);
						var label = target.children('#pieLabel'+index);
						var labelTop = (y - label.height()/2);
						var labelLeft = (x - label.width()/2);
						label.css('top', labelTop);
						label.css('left', labelLeft);
						
						// check to make sure that the label is not outside the canvas
						if (0-labelTop>0 || 0-labelLeft>0 || canvas.height-(labelTop+label.height())<0 || canvas.width-(labelLeft+label.width())<0)
							redraw = true;
						
						if (options.series.pie.label.background.opacity != 0) {
							// put in the transparent background separately to avoid blended labels and label boxes
							var c = options.series.pie.label.background.color;
							if (c == null) {
								c = slice.color;
							}
							var pos = 'top:'+labelTop+'px;left:'+labelLeft+'px;';
							$('<div class="pieLabelBackground" style="position:absolute;width:' + label.width() + 'px;height:' + label.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').insertBefore(label).css('opacity', options.series.pie.label.background.opacity);
						}
					} // end individual label function
				} // end drawLabels function
			} // end drawPie function
		} // end draw function
		
		// Placed here because it needs to be accessed from multiple locations 
		function drawDonutHole(layer)
		{
			// draw donut hole
			if(options.series.pie.innerRadius > 0)
			{
				// subtract the center
				layer.save();
				innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius;
				layer.globalCompositeOperation = 'destination-out'; // this does not work with excanvas, but it will fall back to using the stroke color
				layer.beginPath();
				layer.fillStyle = options.series.pie.stroke.color;
				layer.arc(0,0,innerRadius,0,Math.PI*2,false);
				layer.fill();
				layer.closePath();
				layer.restore();
				
				// add inner stroke
				layer.save();
				layer.beginPath();
				layer.strokeStyle = options.series.pie.stroke.color;
				layer.arc(0,0,innerRadius,0,Math.PI*2,false);
				layer.stroke();
				layer.closePath();
				layer.restore();
				// TODO: add extra shadow inside hole (with a mask) if the pie is tilted.
			}
		}
		
		//-- Additional Interactive related functions --
		
		function isPointInPoly(poly, pt)
		{
			for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
				((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1]))
				&& (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])
				&& (c = !c);
			return c;
		}
		
		function findNearbySlice(mouseX, mouseY)
		{
			var slices = plot.getData(),
				options = plot.getOptions(),
				radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
			
			for (var i = 0; i < slices.length; ++i) 
			{
				var s = slices[i];	
				
				if(s.pie.show)
				{
					ctx.save();
					ctx.beginPath();
					ctx.moveTo(0,0); // Center of the pie
					//ctx.scale(1, options.series.pie.tilt);	// this actually seems to break everything when here.
					ctx.arc(0,0,radius,s.startAngle,s.startAngle+s.angle,false);
					ctx.closePath();
					x = mouseX-centerLeft;
					y = mouseY-centerTop;
					if(ctx.isPointInPath)
					{
						if (ctx.isPointInPath(mouseX-centerLeft, mouseY-centerTop))
						{
							//alert('found slice!');
							ctx.restore();
							return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
						}
					}
					else
					{
						// excanvas for IE doesn;t support isPointInPath, this is a workaround. 
						p1X = (radius * Math.cos(s.startAngle));
						p1Y = (radius * Math.sin(s.startAngle));
						p2X = (radius * Math.cos(s.startAngle+(s.angle/4)));
						p2Y = (radius * Math.sin(s.startAngle+(s.angle/4)));
						p3X = (radius * Math.cos(s.startAngle+(s.angle/2)));
						p3Y = (radius * Math.sin(s.startAngle+(s.angle/2)));
						p4X = (radius * Math.cos(s.startAngle+(s.angle/1.5)));
						p4Y = (radius * Math.sin(s.startAngle+(s.angle/1.5)));
						p5X = (radius * Math.cos(s.startAngle+s.angle));
						p5Y = (radius * Math.sin(s.startAngle+s.angle));
						arrPoly = [[0,0],[p1X,p1Y],[p2X,p2Y],[p3X,p3Y],[p4X,p4Y],[p5X,p5Y]];
						arrPoint = [x,y];
						// TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt?
						if(isPointInPoly(arrPoly, arrPoint))
						{
							ctx.restore();
							return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
						}			
					}
					ctx.restore();
				}
			}
			
			return null;
		}

		function onMouseMove(e) 
		{
			triggerClickHoverEvent('plothover', e);
		}
		
        function onClick(e) 
		{
			triggerClickHoverEvent('plotclick', e);
        }

		// trigger click or hover event (they send the same parameters so we share their code)
		function triggerClickHoverEvent(eventname, e) 
		{
			var offset = plot.offset(),
				canvasX = parseInt(e.pageX - offset.left),
				canvasY =  parseInt(e.pageY - offset.top),
				item = findNearbySlice(canvasX, canvasY);
			
			if (options.grid.autoHighlight) 
			{
				// clear auto-highlights
				for (var i = 0; i < highlights.length; ++i) 
				{
					var h = highlights[i];
					if (h.auto == eventname && !(item && h.series == item.series))
						unhighlight(h.series);
				}
			}
			
			// highlight the slice
			if (item) 
			    highlight(item.series, eventname);
				
			// trigger any hover bind events
			var pos = { pageX: e.pageX, pageY: e.pageY };
			target.trigger(eventname, [ pos, item ]);	
		}

		function highlight(s, auto) 
		{
			if (typeof s == "number")
				s = series[s];

			var i = indexOfHighlight(s);
			if (i == -1) 
			{
				highlights.push({ series: s, auto: auto });
				plot.triggerRedrawOverlay();
			}
			else if (!auto)
				highlights[i].auto = false;
		}

		function unhighlight(s) 
		{
			if (s == null) 
			{
				highlights = [];
				plot.triggerRedrawOverlay();
			}
			
			if (typeof s == "number")
				s = series[s];

			var i = indexOfHighlight(s);
			if (i != -1) 
			{
				highlights.splice(i, 1);
				plot.triggerRedrawOverlay();
			}
		}

		function indexOfHighlight(s) 
		{
			for (var i = 0; i < highlights.length; ++i) 
			{
				var h = highlights[i];
				if (h.series == s)
					return i;
			}
			return -1;
		}

		function drawOverlay(plot, octx) 
		{
			//alert(options.series.pie.radius);
			var options = plot.getOptions();
			//alert(options.series.pie.radius);
			
			var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;

			octx.save();
			octx.translate(centerLeft, centerTop);
			octx.scale(1, options.series.pie.tilt);
			
			for (i = 0; i < highlights.length; ++i) 
				drawHighlight(highlights[i].series);
			
			drawDonutHole(octx);

			octx.restore();

			function drawHighlight(series) 
			{
				if (series.angle < 0) return;
				
				//octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString();
				octx.fillStyle = "rgba(255, 255, 255, "+options.series.pie.highlight.opacity+")"; // this is temporary until we have access to parseColor
				
				octx.beginPath();
				if (Math.abs(series.angle - Math.PI*2) > 0.000000001)
					octx.moveTo(0,0); // Center of the pie
				octx.arc(0,0,radius,series.startAngle,series.startAngle+series.angle,false);
				octx.closePath();
				octx.fill();
			}
			
		}	
		
	} // end init (plugin body)
	
	// define pie specific options and their default values
	var options = {
		series: {
			pie: {
				show: false,
				radius: 'auto',	// actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value)
				innerRadius:0, /* for donut */
				startAngle: 3/2,
				tilt: 1,
				offset: {
					top: 0,
					left: 'auto'
				},
				stroke: {
					color: '#FFF',
					width: 1
				},
				label: {
					show: 'auto',
					formatter: function(label, slice){
						return '<div style="font-size:x-small;text-align:center;padding:2px;color:'+slice.color+';">'+label+'<br/>'+Math.round(slice.percent)+'%</div>';
					},	// formatter function
					radius: 1,	// radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value)
					background: {
						color: null,
						opacity: 0
					},
					threshold: 0	// percentage at which to hide the label (i.e. the slice is too narrow)
				},
				combine: {
					threshold: -1,	// percentage at which to combine little slices into one larger slice
					color: null,	// color to give the new slice (auto-generated if null)
					label: 'Other'	// label to give the new slice
				},
				highlight: {
					//color: '#FFF',		// will add this functionality once parseColor is available
					opacity: 0.5
				}
			}
		}
	};
    
	$.plot.plugins.push({
		init: init,
		options: options,
		name: "pie",
		version: "1.0"
	});
})(jQuery);
