/**
 * The `Ext.d3.legend.Color` is designed to work with the {@link Ext.d3.axis.Color Color} axis
 * and present the range of its possible values in various ways.
 */
Ext.define('Ext.d3.legend.Color', {
    extend: 'Ext.d3.legend.Legend',

    requires: [
        'Ext.d3.Helpers'
    ],

    config: {
        /**
         * @cfg {Ext.d3.axis.Color} axis
         * The color axis that this legend represents.
         */
        axis: null,

        /**
         * @cfg {Object} items
         * @cfg {Number} items.count The number of legend items to use to represent
         * the range of possible values of the color axis scale.
         * This config makes use of the `ticks` method of the color axis
         * scale. Please see the method's [documentation](https://github.com/d3/d3-3.x-api-reference/blob/master/Quantitative-Scales.md#user-content-linear_ticks)
         * for more info.
         * This number is only a hint, the actual number may be different.
         * @cfg {Number[]} items.slice Arguments to the Array's `slice` method.
         * For example, to skip the first legend item use the value of `[1]`,
         * to skip the first and last item: `[1, -1]`.
         * @cfg {Boolean} items.reverse Set to `true` to reverse the order of items in the legend.
         * Note: the slicing of items happens before the order is reversed.
         * @cfg {Object} items.size The size of a single legend item.
         * @cfg {Number} items.size.x The width of a legend item.
         * @cfg {Number} items.size.y The height of a legend item.
         */
        items: {
            count: 5,
            slice: null,
            reverse: false,
            size: {
                x: 30,
                y: 30
            }
        }
    },

    getScale: function() {
        return this.getAxis().getScale();
    },

    updateAxis: function(axis, oldAxis) {
        var me = this;

        if (oldAxis) {
            oldAxis.un('scalechange', me.onScaleChange, me);
        }

        if (axis) {
            axis.on('scalechange', me.onScaleChange, me);
        }
    },

    onScaleChange: function(axis, scale) {
        this.renderItems();
    },

    updateItems: function() {
        if (!this.isConfiguring) {
            this.renderItems();
        }
    },

    renderItems: function() {
        var me = this,
            scale = me.getScale(),
            items = me.getItems(),
            itemSelection = me.getRenderedItems(),
            ticks, updateSelection;

        if (items.count > 0 && scale.ticks) {
            ticks = scale.ticks(items.count);

            if (items.slice) {
                ticks = ticks.slice.apply(ticks, items.slice);
            }

            if (items.reverse) {
                ticks = ticks.reverse();
            }
        }
        else {
            ticks = scale.domain();
        }

        if (ticks) {
            updateSelection = itemSelection.data(ticks);

            me.onAddItems(updateSelection.enter());
            me.onUpdateItems(updateSelection);
            me.onRemoveItems(updateSelection.exit());
        }
    },

    getRenderedItems: function() {
        return this.group.selectAll('.' + this.defaultCls.item);
    },

    onAddItems: function(selection) {
        var me = this;

        selection = selection.append('g').classed(me.defaultCls.item, true);
        selection.append('rect');
        selection.append('text');
        me.onUpdateItems(selection);
    },

    onUpdateItems: function(selection) {
        var me = this,
            items = me.getItems(),
            docked = me.getDocked(),
            scale = me.getScale(),
            blocks, labels;

        blocks = selection.select('rect')
            .attr('width', items.size.x)
            .attr('height', items.size.y)
            .style('fill', scale);

        labels = selection.select('text')
            .each(function() {
                Ext.d3.Helpers.setDominantBaseline(this, 'middle');
            })
            .attr('text-anchor', 'middle')
            .text(String);

        switch (docked) {
            case 'left':
            case 'right':
                blocks.attr('transform', function(data, index) {
                    return 'translate(0,' + index * items.size.y + ')';
                });
                labels
                    .attr('x', items.size.x + 10)
                    .attr('y', function(data, index) {
                        return (index + 0.5) * items.size.y;
                    })
                    .attr('dx', 10);
                break;
            case 'top':
            case 'bottom':
                blocks.attr('transform', function(data, index) {
                    return 'translate(' + index * items.size.x + ',0)';
                });
                labels
                    .attr('x', function(data, index) {
                        return (index + 0.5) * items.size.x;
                    })
                    .attr('y', items.size.y)
                    .attr('dy', '1em');
                break;
        }
    },

    onRemoveItems: function(selection) {
        selection.remove();
    }

});
