(function(){

"use strict";

var root = this,
        Chart = root.Chart,
        //Cache a local reference to Chart.helpers
        helpers = Chart.helpers;

var defaultConfig = {
        //Boolean - Show a backdrop to the scale label
        scaleShowLabelBackdrop : true,

        //String - The colour of the label backdrop
        scaleBackdropColor : "rgba(255,255,255,0.75)",

        // Boolean - Whether the scale should begin at zero
        scaleBeginAtZero : true,

        //Number - The backdrop padding above & below the label in pixels
        scaleBackdropPaddingY : 2,

        //Number - The backdrop padding to the side of the label in pixels
        scaleBackdropPaddingX : 2,

        //Boolean - Show line for each value in the scale
        scaleShowLine : true,

        //Boolean - Stroke a line around each segment in the chart
        segmentShowStroke : true,

        //String - The colour of the stroke on each segement.
        segmentStrokeColor : "#fff",

        //Number - The width of the stroke value in pixels
        segmentStrokeWidth : 2,

        //Number - Amount of animation steps
        animationSteps : 100,

        //String - Animation easing effect.
        animationEasing : "easeOutBounce",

        //Boolean - Whether to animate the rotation of the chart
        animateRotate : true,

        //Boolean - Whether to animate scaling the chart 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: "PolarArea",
        //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){
                this.segments = [];
                //Declare segment class as a chart instance specific class, so it can share props for this instance
                this.SegmentArc = Chart.Arc.extend({
                        showStroke : this.options.segmentShowStroke,
                        strokeWidth : this.options.segmentStrokeWidth,
                        strokeColor : this.options.segmentStrokeColor,
                        ctx : this.chart.ctx,
                        innerRadius : 0,
                        x : this.chart.width/2,
                        y : this.chart.height/2
                });
                this.scale = new Chart.RadialScale({
                        display: this.options.showScale,
                        fontStyle: this.options.scaleFontStyle,
                        fontSize: this.options.scaleFontSize,
                        fontFamily: this.options.scaleFontFamily,
                        fontColor: this.options.scaleFontColor,
                        showLabels: this.options.scaleShowLabels,
                        showLabelBackdrop: this.options.scaleShowLabelBackdrop,
                        backdropColor: this.options.scaleBackdropColor,
                        backdropPaddingY : this.options.scaleBackdropPaddingY,
                        backdropPaddingX: this.options.scaleBackdropPaddingX,
                        lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
                        lineColor: this.options.scaleLineColor,
                        lineArc: true,
                        width: this.chart.width,
                        height: this.chart.height,
                        xCenter: this.chart.width/2,
                        yCenter: this.chart.height/2,
                        ctx : this.chart.ctx,
                        templateString: this.options.scaleLabel,
                        valuesCount: data.length
                });

                this.updateScaleRange(data);

                this.scale.update();

                helpers.each(data,function(segment,index){
                        this.addData(segment,index,true);
                },this);

                //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.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({
                        fillColor: segment.color,
                        highlightColor: segment.highlight || segment.color,
                        label: segment.label,
                        value: segment.value,
                        outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),
                        circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),
                        startAngle: Math.PI * 1.5
                }));
                if (!silent){
                        this.reflow();
                        this.update();
                }
        },
        removeData: function(atIndex){
                var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
                this.segments.splice(indexToDelete, 1);
                this.reflow();
                this.update();
        },
        calculateTotal: function(data){
                this.total = 0;
                helpers.each(data,function(segment){
                        this.total += segment.value;
                },this);
                this.scale.valuesCount = this.segments.length;
        },
        updateScaleRange: function(datapoints){
                var valuesArray = [];
                helpers.each(datapoints,function(segment){
                        valuesArray.push(segment.value);
                });

                var scaleSizes = (this.options.scaleOverride) ?
                        {
                                steps: this.options.scaleSteps,
                                stepValue: this.options.scaleStepWidth,
                                min: this.options.scaleStartValue,
                                max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
                        } :
                        helpers.calculateScaleRange(
                                valuesArray,
                                helpers.min([this.chart.width, this.chart.height])/2,
                                this.options.scaleFontSize,
                                this.options.scaleBeginAtZero,
                                this.options.scaleIntegersOnly
                        );

                helpers.extend(
                        this.scale,
                        scaleSizes,
                        {
                                size: helpers.min([this.chart.width, this.chart.height]),
                                xCenter: this.chart.width/2,
                                yCenter: this.chart.height/2
                        }
                );

        },
        update : function(){
                this.calculateTotal(this.segments);

                helpers.each(this.segments,function(segment){
                        segment.save();
                });

                this.reflow();
                this.render();
        },
        reflow : function(){
                helpers.extend(this.SegmentArc.prototype,{
                        x : this.chart.width/2,
                        y : this.chart.height/2
                });
                this.updateScaleRange(this.segments);
                this.scale.update();

                helpers.extend(this.scale,{
                        xCenter: this.chart.width/2,
                        yCenter: this.chart.height/2
                });

                helpers.each(this.segments, function(segment){
                        segment.update({
                                outerRadius : this.scale.calculateCenterOffset(segment.value)
                        });
                }, this);

        },
        draw : function(ease){
                var easingDecimal = ease || 1;
                //Clear & draw the canvas
                this.clear();
                helpers.each(this.segments,function(segment, index){
                        segment.transition({
                                circumference : this.scale.getCircumference(),
                                outerRadius : this.scale.calculateCenterOffset(segment.value)
                        },easingDecimal);

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

                        // If we've removed the first segment we need to set the first one to
                        // start at the top.
                        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;
                        }
                        segment.draw();
                }, this);
                this.scale.draw();
        }
});

}).call(this);