// TODO Batch by color

define(function (require) {

    var graphic = require('../../util/graphic');
    var symbolUtil = require('../../util/symbol');

    var LargeSymbolPath = graphic.extendShape({

        shape: {
            points: null,
            sizes: null
        },

        symbolProxy: null,

        buildPath: function (path, shape) {
            var points = shape.points;
            var sizes = shape.sizes;

            var symbolProxy = this.symbolProxy;
            var symbolProxyShape = symbolProxy.shape;
            for (var i = 0; i < points.length; i++) {
                var pt = points[i];
                var size = sizes[i];
                if (size[0] < 4) {
                    // Optimize for small symbol
                    path.rect(
                        pt[0] - size[0] / 2, pt[1] - size[1] / 2,
                        size[0], size[1]
                    );
                }
                else {
                    symbolProxyShape.x = pt[0] - size[0] / 2;
                    symbolProxyShape.y = pt[1] - size[1] / 2;
                    symbolProxyShape.width = size[0];
                    symbolProxyShape.height = size[1];

                    symbolProxy.buildPath(path, symbolProxyShape, true);
                }
            }
        },

        findDataIndex: function (x, y) {
            var shape = this.shape;
            var points = shape.points;
            var sizes = shape.sizes;

            // Not consider transform
            // Treat each element as a rect
            // top down traverse
            for (var i = points.length - 1; i >= 0; i--) {
                var pt = points[i];
                var size = sizes[i];
                var x0 = pt[0] - size[0] / 2;
                var y0 = pt[1] - size[1] / 2;
                if (x >= x0 && y >= y0 && x <= x0 + size[0] && y <= y0 + size[1]) {
                    // i is dataIndex
                    return i;
                }
            }

            return -1;
        }
    });

    function LargeSymbolDraw() {
        this.group = new graphic.Group();

        this._symbolEl = new LargeSymbolPath({
            // rectHover: true,
            // cursor: 'default'
        });
    }

    var largeSymbolProto = LargeSymbolDraw.prototype;

    /**
     * Update symbols draw by new data
     * @param {module:echarts/data/List} data
     */
    largeSymbolProto.updateData = function (data) {
        this.group.removeAll();

        var symbolEl = this._symbolEl;

        var seriesModel = data.hostModel;

        symbolEl.setShape({
            points: data.mapArray(data.getItemLayout),
            sizes: data.mapArray(
                function (idx) {
                    var size = data.getItemVisual(idx, 'symbolSize');
                    if (!(size instanceof Array)) {
                        size = [size, size];
                    }
                    return size;
                }
            )
        });

        // Create symbolProxy to build path for each data
        symbolEl.symbolProxy = symbolUtil.createSymbol(
            data.getVisual('symbol'), 0, 0, 0, 0
        );
        // Use symbolProxy setColor method
        symbolEl.setColor = symbolEl.symbolProxy.setColor;

        symbolEl.useStyle(
            seriesModel.getModel('itemStyle.normal').getItemStyle(['color'])
        );

        var visualColor = data.getVisual('color');
        if (visualColor) {
            symbolEl.setColor(visualColor);
        }

        // Enable tooltip
        // PENDING May have performance issue when path is extremely large
        symbolEl.seriesIndex = seriesModel.seriesIndex;
        symbolEl.on('mousemove', function (e) {
            symbolEl.dataIndex = null;
            var dataIndex = symbolEl.findDataIndex(e.offsetX, e.offsetY);
            if (dataIndex > 0) {
                // Provide dataIndex for tooltip
                symbolEl.dataIndex = dataIndex;
            }
        });

        // Add back
        this.group.add(symbolEl);
    };

    largeSymbolProto.updateLayout = function (seriesModel) {
        var data = seriesModel.getData();
        this._symbolEl.setShape({
            points: data.mapArray(data.getItemLayout)
        });
    };

    largeSymbolProto.remove = function () {
        this.group.removeAll();
    };

    return LargeSymbolDraw;
});