(function(){

	"use strict";



	var root = this,

		Chart = root.Chart,

		//Cache a local reference to Chart.helpers

		helpers = Chart.helpers;



	var defaultConfig = {

		//Boolean - Whether we should show a stroke on each segment

		segmentShowStroke : true,



		//String - The colour of each segment stroke

		segmentStrokeColor : "#fff",



		//Number - The width of each segment stroke

		segmentStrokeWidth : 2,



		//The percentage of the chart that we cut out of the middle.

		percentageInnerCutout : 50,



		//Number - Amount of animation steps

		animationSteps : 100,



		//String - Animation easing effect

		animationEasing : "easeOutBounce",



		//Boolean - Whether we animate the rotation of the Doughnut

		animateRotate : true,



		//Boolean - Whether we animate scaling the Doughnut from the centre

		animateScale : false,



		//String - A legend template

		legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"><%if(segments[i].label){%><%=segments[i].label%><%}%></span></li><%}%></ul>"



	};



	Chart.Type.extend({

		//Passing in a name registers this chart in the Chart namespace

		name: "Doughnut",

		//Providing a defaults will also register the deafults in the chart namespace

		defaults : defaultConfig,

		//Initialize is fired when the chart is initialized - Data is passed in as a parameter

		//Config is automatically merged by the core of Chart.js, and is available at this.options

		initialize:  function(data){



			//Declare segments as a static property to prevent inheriting across the Chart type prototype

			this.segments = [];

			this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) -	this.options.segmentStrokeWidth/2)/2;



			this.SegmentArc = Chart.Arc.extend({

				ctx : this.chart.ctx,

				x : this.chart.width/2,

				y : this.chart.height/2

			});



			//Set up tooltip events on the chart

			if (this.options.showTooltips){

				helpers.bindEvents(this, this.options.tooltipEvents, function(evt){

					var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];



					helpers.each(this.segments,function(segment){

						segment.restore(["fillColor"]);

					});

					helpers.each(activeSegments,function(activeSegment){

						activeSegment.fillColor = activeSegment.highlightColor;

					});

					this.showTooltip(activeSegments);

				});

			}

			this.calculateTotal(data);



			helpers.each(data,function(datapoint, index){

				if (!datapoint.color) {

					datapoint.color = 'hsl(' + (360 * index / data.length) + ', 100%, 50%)';

				}

				this.addData(datapoint, index, true);

			},this);



			this.render();

		},

		getSegmentsAtEvent : function(e){

			var segmentsArray = [];



			var location = helpers.getRelativePosition(e);



			helpers.each(this.segments,function(segment){

				if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);

			},this);

			return segmentsArray;

		},

		addData : function(segment, atIndex, silent){

			var index = atIndex !== undefined ? atIndex : this.segments.length;

			this.segments.splice(index, 0, new this.SegmentArc({

				value : segment.value,

				outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,

				innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,

				fillColor : segment.color,

				highlightColor : segment.highlight || segment.color,

				showStroke : this.options.segmentShowStroke,

				strokeWidth : this.options.segmentStrokeWidth,

				strokeColor : this.options.segmentStrokeColor,

				startAngle : Math.PI * 1.5,

				circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),

				label : segment.label

			}));

			if (!silent){

				this.reflow();

				this.update();

			}

		},

		calculateCircumference : function(value) {

			if ( this.total > 0 ) {

				return (Math.PI*2)*(value / this.total);

			} else {

				return 0;

			}

		},

		calculateTotal : function(data){

			this.total = 0;

			helpers.each(data,function(segment){

				this.total += Math.abs(segment.value);

			},this);

		},

		update : function(){

			this.calculateTotal(this.segments);



			// Reset any highlight colours before updating.

			helpers.each(this.activeElements, function(activeElement){

				activeElement.restore(['fillColor']);

			});



			helpers.each(this.segments,function(segment){

				segment.save();

			});

			this.render();

		},



		removeData: function(atIndex){

			var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;

			this.segments.splice(indexToDelete, 1);

			this.reflow();

			this.update();

		},



		reflow : function(){

			helpers.extend(this.SegmentArc.prototype,{

				x : this.chart.width/2,

				y : this.chart.height/2

			});

			this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) -	this.options.segmentStrokeWidth/2)/2;

			helpers.each(this.segments, function(segment){

				segment.update({

					outerRadius : this.outerRadius,

					innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout

				});

			}, this);

		},

		draw : function(easeDecimal){

			var animDecimal = (easeDecimal) ? easeDecimal : 1;

			this.clear();

			helpers.each(this.segments,function(segment,index){

				segment.transition({

					circumference : this.calculateCircumference(segment.value),

					outerRadius : this.outerRadius,

					innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout

				},animDecimal);



				segment.endAngle = segment.startAngle + segment.circumference;



				segment.draw();

				if (index === 0){

					segment.startAngle = Math.PI * 1.5;

				}

				//Check to see if it's the last segment, if not get the next and update the start angle

				if (index < this.segments.length-1){

					this.segments[index+1].startAngle = segment.endAngle;

				}

			},this);



		}

	});



	Chart.types.Doughnut.extend({

		name : "Pie",

		defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})

	});



}).call(this);

