/**
 * @class Ext.sparkline.TriState
 *
 * Plots bars based upon "win"/"draw" or "lose" status of the input {@link #values} array.
 * Positive values mean a win, zero a draw, and negative a lose. 
 *
 * See {@link Ext.sparkline.Base the base class} for a simple example.
 */
Ext.define('Ext.sparkline.TriState', {
    extend: 'Ext.sparkline.BarBase',
    requires: [
        'Ext.sparkline.RangeMap'
    ],
 
    alias: 'widget.sparklinetristate',
 
    config: {
 
        /**
         * @cfg {Number} barWidth
         * The pixel width of each bar.
         */
        barWidth: 4,
        
        /**
         * @cfg {Number} barSpacing
         * The pixel spacing between each bar.
         */
        barSpacing: 1,
        
        /**
         * @cfg {String} posBarColor
         * The color for positive value bars.
         */
        posBarColor: '#6f6',
        
        /**
         * @cfg {String} negBarColor
         * The color for negative value bars.
         */
        negBarColor: '#f44',
        
        /**
         * @cfg {String} zeroBarColor
         * The color for zero value bars.
         */
        zeroBarColor: '#999',
        
        /**
         * @cfg {Object} colorMap
         * An object that uses range specifiers as keys to
         * indicate bar color values for a range of values. A range specifier is
         * specified in the form `[number]:[number]`, which indicates start and end range.
         * Omitting either means an open ended range.
         *
         * For example, to render green bars on all values less than -1 and red on values
         * higher than 1, you would use:
         *
         *     colorMap: {
         *         // Open ended range, with max value -1
         *         ":-1": "green",
         *
         *         // Open ended range, with min value 1
         *         "1:": "red"
         *     }
         */
        colorMap: {}
    },
 
    tipTpl: ['● {value:this.states}', {
        states: function(v) {
            var value = Number(v);
 
            if (value === -1) {
                return 'Loss';
            }
 
            if (value === 0) {
                return 'Draw';
            }
 
            if (value === 1) {
                return 'Win';
            }
 
            return v;
        }
    }],
 
    applyColorMap: function(colorMap) {
        var me = this;
 
        if (Ext.isArray(colorMap)) {
            me.colorMapByIndex = colorMap;
            me.colorMapByValue = null;
        }
        else {
            me.colorMapByIndex = null;
            me.colorMapByValue = colorMap;
 
            if (me.colorMapByValue && me.colorMapByValue.get == null) {
                me.colorMapByValue = new Ext.sparkline.RangeMap(colorMap);
            }
        }
 
        me.updateConfigChange();
 
        return colorMap;
    },
 
    // 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.updateConfigChange();
 
        return newValues;
    },
 
    onUpdate: function() {
        this.totalBarWidth = this.getBarWidth() + this.getBarSpacing();
    },
 
    getBarWidth: function() {
        var values = this.values;
 
        return this._barWidth ||
               (this.getWidth() - (values.length - 1) * this.getBarSpacing()) / values.length;
    },
 
    getRegion: function(x, y) {
        return Math.floor(/ this.totalBarWidth);
    },
 
    getRegionFields: function(region) {
        return {
            isNull: this.values[region] == null,
            value: this.values[region],
            color: this.calcColor(this.values[region], region),
            offset: region
        };
    },
 
    calcColor: function(value, valuenum) {
        var me = this,
            values = me.values,
            colorMapByIndex = me.colorMapByIndex,
            colorMapByValue = me.colorMapByValue,
            color, newColor;
 
        if (colorMapByValue && (newColor = colorMapByValue.get(value))) {
            color = newColor;
        }
        else if (colorMapByIndex && colorMapByIndex.length > valuenum) {
            color = colorMapByIndex[valuenum];
        }
        else if (values[valuenum] < 0) {
            color = me.getNegBarColor();
        }
        else if (values[valuenum] > 0) {
            color = me.getPosBarColor();
        }
        else {
            color = me.getZeroBarColor();
        }
 
        return color;
    },
 
    renderRegion: function(valuenum, highlight) {
        var me = this,
            values = me.values,
            canvas = me.canvas,
            canvasHeight, height, halfHeight, x, y, color;
 
        canvasHeight = canvas.pixelHeight;
        halfHeight = Math.round(canvasHeight / 2);
 
        x = valuenum * me.totalBarWidth;
 
        if (values[valuenum] < 0) {
            y = halfHeight;
            height = halfHeight - 1;
        }
        else if (values[valuenum] > 0) {
            y = 0;
            height = halfHeight - 1;
        }
        else {
            y = halfHeight - 1;
            height = 2;
        }
 
        color = me.calcColor(values[valuenum], valuenum);
 
        if (color == null) {
            return;
        }
 
        if (highlight) {
            color = me.calcHighlightColor(color);
        }
 
        canvas.drawRect(x, y, me.getBarWidth() - 1, height - 1, color, color).append();
    }
});