/**
 * @class Ext.sparkline.Pie
 *
 * Plots a pie chart based upon the input {#values} array.
 *
 * See {@link Ext.sparkline.Base the base class} for a simple example.
 */
Ext.define('Ext.sparkline.Pie', {
    extend: 'Ext.sparkline.Base',

    alias: 'widget.sparklinepie',

    config: {

        /**
         * @cfg {Number} [offset] Angle in degrees to offset the first slice.
         */
        offset: 0,
        
        /**
         * @cfg {String[]} [sliceColors] An array of CSS colro values to apply to the chart slices.
         */
        sliceColors: ['#3366cc', '#dc3912', '#ff9900', '#109618', '#66aa00', '#dd4477', '#0099c6', '#990099'],
        
        /**
         * @cfg {Number} [borderWidth=0] Border width in pixels of line round slices.
         */
        borderWidth: 0,
        
        /**
         * @cfg {String} [borderColor=#000] Border color of line round slices.
         */
        borderColor: '#000'
    },

    tipTpl: '&#9679; {value} ({percent:number("0.0")}%)',

    // Ensure values is an array of numbers
    applyValues: function(newValues) {
        newValues = Ext.Array.map(Ext.Array.from(newValues), Number);
        this.disabled = !(newValues && newValues.length);
        this.applyConfigChange();
        return newValues;
    },

    onUpdate: function () {
        var me = this,
            values = me.values,
            total = 0, i;

        me.callParent(arguments);

        me.shapes = {}; // map shape ids to value offsets
        me.valueShapes = {}; // maps value offsets to shape ids

        if (values.length > 0) {
            for (i = values.length; i--;) {
                total += values[i];
            }
        }
        me.total = total;
        me.radius = Math.floor(Math.min(me.getWidth(), me.getHeight()) / 2);
    },

    getRegion: function(x, y) {
        var ratio = window.devicePixelRatio || 1,
            shapeid = this.canvas.getShapeAt(x * ratio, y * ratio);
        return (shapeid != null && this.shapes[shapeid] != null) ? this.shapes[shapeid] : null;
    },

    getRegionFields: function(region) {
        var sliceColors = this.getSliceColors();

        return {
            isNull: this.values[region] == null,
            value: this.values[region],
            percent: this.values[region] / this.total * 100,
            color: sliceColors[region % sliceColors.length],
            offset: region
        };
    },

    renderHighlight: function(region) {
        this.renderSlice(region, true).append();
    },

    renderSlice: function(valuenum, highlight) {
        var me = this,
            canvas = me.canvas,
            radius = me.radius,
            borderWidth = me.getBorderWidth(),
            offset = me.getOffset(),
            circle = 2 * Math.PI,
            values = me.values,
            total = me.total,
            next = offset ? (2*Math.PI)*(offset/360) : 0,
            start, end, i, vlen, color,
            sliceColors = this.getSliceColors();

        vlen = values.length;
        for (i = 0; i < vlen; i++) {
            start = next;
            end = next;
            if (total > 0) {  // avoid divide by zero
                end = next + (circle * (values[i] / total));
            }
            if (valuenum === i) {
                color = sliceColors[i % sliceColors.length];
                if (highlight) {
                    color = me.calcHighlightColor(color);
                }

                return canvas.drawPieSlice(radius, radius, radius - borderWidth, start, end, null, color);
            }
            next = end;
        }
    },

    renderGraph: function () {
        var me = this,
            canvas = me.canvas,
            values = me.values,
            radius = me.radius,
            borderWidth = me.getBorderWidth(),
            shape, i,
            shapes = me.shapes || (me.shapes = {}),
            valueShapes = me.valueShapes || (me.valueShapes = {});

        if (!me.callParent()) {
            return;
        }
        if (borderWidth) {
            canvas.drawCircle(radius, radius, Math.floor(radius - (borderWidth / 2)),
                me.getBorderColor(), null, borderWidth).append();
        }
        for (i = values.length; i--;) {
            if (values[i]) { // don't render zero values
                shape = me.renderSlice(i).append();
                valueShapes[i] = shape.id; // store just the shapeid
                shapes[shape.id] = i;
            }
        }

        // If mouse is over, re-apply the highlight
        if (me.currentPageXY && me.el.getRegion().contains(me.currentPageXY)) {
            me.currentRegion = null;
            me.updateDisplay();
        }
        canvas.render();
    }
});