(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%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></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){
                        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 || 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){
                return (Math.PI*2)*(Math.abs(value) / this.total);
        },
        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);