/**
 * echarts组件:值域
 *
 * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *
 */
define(function (require) {
    var Base = require('./base');
    
    // 图形依赖
    var TextShape = require('zrender/shape/Text');
    var RectangleShape = require('zrender/shape/Rectangle');
    var HandlePolygonShape = require('../util/shape/HandlePolygon');

    var ecConfig = require('../config');
    // 值域
    ecConfig.dataRange = {
        zlevel: 0,                  // 一级层叠
        z: 4,                       // 二级层叠
        show: true,
        orient: 'vertical',        // 布局方式,默认为垂直布局,可选为:
                                   // 'horizontal' ¦ 'vertical'
        x: 'left',                 // 水平安放位置,默认为全图左对齐,可选为:
                                   // 'center' ¦ 'left' ¦ 'right'
                                   // ¦ {number}(x坐标,单位px)
        y: 'bottom',               // 垂直安放位置,默认为全图底部,可选为:
                                   // 'top' ¦ 'bottom' ¦ 'center'
                                   // ¦ {number}(y坐标,单位px)
        backgroundColor: 'rgba(0,0,0,0)',
        borderColor: '#ccc',       // 值域边框颜色
        borderWidth: 0,            // 值域边框线宽,单位px,默认为0(无边框)
        padding: 5,                // 值域内边距,单位px,默认各方向内边距为5,
                                   // 接受数组分别设定上右下左边距,同css
        itemGap: 10,               // 各个item之间的间隔,单位px,默认为10,
                                   // 横向布局时为水平间隔,纵向布局时为纵向间隔
        itemWidth: 20,             // 值域图形宽度,线性渐变水平布局宽度为该值 * 10
        itemHeight: 14,            // 值域图形高度,线性渐变垂直布局高度为该值 * 10
        // min: null,              // 最小值
        // max: null,              // 最大值
        precision: 0,              // 小数精度,默认为0,无小数点
        splitNumber: 5,            // 分割段数,默认为5,为0时为线性渐变
        calculable: false,         // 是否值域漫游,启用后无视splitNumber,线性渐变
        selectedMode: true,        // 选择模式,默认开启值域开关
        hoverLink: true,
        realtime: true,
        color:['#006edd','#e0ffff'],//颜色 
        // formatter: null,
        // text:['高','低'],         // 文本,默认为数值文本
        textStyle: {
            color: '#333'          // 值域文字颜色
        }
    };

    var zrUtil = require('zrender/tool/util');
    var zrEvent = require('zrender/tool/event');
    var zrArea = require('zrender/tool/area');
    var zrColor = require('zrender/tool/color');

    /**
     * 构造函数
     * @param {Object} messageCenter echart消息中心
     * @param {ZRender} zr zrender实例
     * @param {Object} option 图表参数
     * @param {Object=} selected 用于状态保持
     */
    function DataRange(ecTheme, messageCenter, zr, option, myChart) {
        if (typeof this.query(option, 'dataRange.min') == 'undefined'
            || typeof this.query(option, 'dataRange.max') == 'undefined'
        ) {
            console.error('option.dataRange.min or option.dataRange.max has not been defined.');
            return;
        }
        
        Base.call(this, ecTheme, messageCenter, zr, option, myChart);
        
        var self = this;
        self._ondrift = function(dx, dy) {
            return self.__ondrift(this, dx, dy);
        };
        self._ondragend = function() {
            return self.__ondragend();
        };
        self._dataRangeSelected = function(param) {
            return self.__dataRangeSelected(param);
        };
        self._dispatchHoverLink = function(param) {
            return self.__dispatchHoverLink(param);
        };
        self._onhoverlink = function(params) {
            return self.__onhoverlink(params);
        };
        this._selectedMap = {};
        this._range = {};
        
        this.refresh(option);
        
        messageCenter.bind(ecConfig.EVENT.HOVER, this._onhoverlink);
    }
    
    DataRange.prototype = {
        type : ecConfig.COMPONENT_TYPE_DATARANGE,
        _textGap : 10, // 非值文字间隔
        _buildShape : function () {
            // 值域元素组的位置参数,通过计算所得x, y, width, height
            this._itemGroupLocation = this._getItemGroupLocation();
            this._buildBackground();
            if (this.dataRangeOption.splitNumber <= 0 
                || this.dataRangeOption.calculable
            ) {
                this._buildGradient();
            }
            else {
                this._buildItem();
            }
            
            if (this.dataRangeOption.show) {
                for (var i = 0, l = this.shapeList.length; i < l; i++) {
                    this.zr.addShape(this.shapeList[i]);
                }
            }
            
            this._syncShapeFromRange();
        },

        /**
         * 构建图例型的值域元素
         */
        _buildItem : function () {
            var data = this._valueTextList;
            var dataLength = data.length;
            var itemName;
            var itemShape;
            var textShape;
            var font = this.getFont(this.dataRangeOption.textStyle);

            var lastX = this._itemGroupLocation.x;
            var lastY = this._itemGroupLocation.y;
            var itemWidth = this.dataRangeOption.itemWidth;
            var itemHeight = this.dataRangeOption.itemHeight;
            var itemGap = this.dataRangeOption.itemGap;
            var textHeight = zrArea.getTextHeight('国', font);
            var color;

            if (this.dataRangeOption.orient == 'vertical'
                && this.dataRangeOption.x == 'right'
            ) {
                lastX = this._itemGroupLocation.x
                        + this._itemGroupLocation.width
                        - itemWidth;
            }
            var needValueText = true;
            if (this.dataRangeOption.text) {
                needValueText = false;
                // 第一个文字
                if (this.dataRangeOption.text[0]) {
                    textShape = this._getTextShape(
                        lastX, lastY, this.dataRangeOption.text[0]
                    );
                    if (this.dataRangeOption.orient == 'horizontal') {
                        lastX += zrArea.getTextWidth(
                                     this.dataRangeOption.text[0],
                                     font
                                 )
                                 + this._textGap;
                    }
                    else {
                        lastY += textHeight + this._textGap;
                        textShape.style.y += textHeight / 2 + this._textGap;
                        textShape.style.textBaseline = 'bottom';
                    }
                    this.shapeList.push(new TextShape(textShape));
                }
            }

            for (var i = 0; i < dataLength; i++) {
                itemName = data[i];
                color = this.getColorByIndex(i);
                // 图形
                itemShape = this._getItemShape(
                    lastX, lastY,
                    itemWidth, itemHeight,
                    (this._selectedMap[i] ? color : '#ccc')
                );
                itemShape._idx = i;
                itemShape.onmousemove = this._dispatchHoverLink;
                if (this.dataRangeOption.selectedMode) {
                    itemShape.clickable = true;
                    itemShape.onclick = this._dataRangeSelected;
                }
                this.shapeList.push(new RectangleShape(itemShape));
                
                if (needValueText) {
                    // 文字
                    textShape = {
                        zlevel: this.getZlevelBase(),
                        z: this.getZBase(),
                        style : {
                            x : lastX + itemWidth + 5,
                            y : lastY,
                            color : this._selectedMap[i]
                                    ? this.dataRangeOption.textStyle.color
                                    : '#ccc',
                            text: data[i],
                            textFont: font,
                            textBaseline: 'top'
                        },
                        highlightStyle:{
                            brushType: 'fill'
                        }
                    };
                    if (this.dataRangeOption.orient == 'vertical'
                        && this.dataRangeOption.x == 'right'
                    ) {
                        textShape.style.x -= (itemWidth + 10);
                        textShape.style.textAlign = 'right';
                    }
                    textShape._idx = i;
                    textShape.onmousemove = this._dispatchHoverLink;
                    if (this.dataRangeOption.selectedMode) {
                        textShape.clickable = true;
                        textShape.onclick = this._dataRangeSelected;
                    }
                    this.shapeList.push(new TextShape(textShape));
                }

                if (this.dataRangeOption.orient == 'horizontal') {
                    lastX += itemWidth 
                             + (needValueText ? 5 : 0)
                             + (needValueText 
                               ? zrArea.getTextWidth(itemName, font)
                               : 0)
                             + itemGap;
                }
                else {
                    lastY += itemHeight + itemGap;
                }
            }
            
            if (!needValueText && this.dataRangeOption.text[1]) {
                if (this.dataRangeOption.orient == 'horizontal') {
                    lastX = lastX - itemGap + this._textGap;
                }
                else {
                    lastY = lastY - itemGap + this._textGap;
                }
                // 最后一个文字
                textShape = this._getTextShape(
                    lastX, lastY, this.dataRangeOption.text[1]
                );
                
                if (this.dataRangeOption.orient != 'horizontal') {
                    textShape.style.y -= 5;
                    textShape.style.textBaseline = 'top';
                }

                this.shapeList.push(new TextShape(textShape));
            }
        },
 
        /**
         * 构建渐变型的值域元素 
         */
        _buildGradient : function () {
            var itemShape;
            var textShape;
            var font = this.getFont(this.dataRangeOption.textStyle);

            var lastX = this._itemGroupLocation.x;
            var lastY = this._itemGroupLocation.y;
            var itemWidth = this.dataRangeOption.itemWidth;
            var itemHeight = this.dataRangeOption.itemHeight;
            var textHeight = zrArea.getTextHeight('国', font);
            var mSize = 10;

            
            var needValueText = true;
            if (this.dataRangeOption.text) {
                needValueText = false;
                // 第一个文字
                if (this.dataRangeOption.text[0]) {
                    textShape = this._getTextShape(
                        lastX, lastY, this.dataRangeOption.text[0]
                    );
                    if (this.dataRangeOption.orient == 'horizontal') {
                        lastX += zrArea.getTextWidth(
                                     this.dataRangeOption.text[0],
                                     font
                                 )
                                 + this._textGap;
                    }
                    else {
                        lastY += textHeight + this._textGap;
                        textShape.style.y += textHeight / 2 + this._textGap;
                        textShape.style.textBaseline = 'bottom';
                    }
                    this.shapeList.push(new TextShape(textShape));
                } 
            }
            
            var zrColor = require('zrender/tool/color');
            var per = 1 / (this.dataRangeOption.color.length - 1);
            var colorList = [];
            for (var i = 0, l = this.dataRangeOption.color.length; i < l; i++) {
                colorList.push([i * per, this.dataRangeOption.color[i]]);
            }
            if (this.dataRangeOption.orient == 'horizontal') {
                itemShape = {
                    zlevel: this.getZlevelBase(),
                    z: this.getZBase(),
                    style : {
                        x : lastX,
                        y : lastY,
                        width : itemWidth * mSize,
                        height : itemHeight,
                        color : zrColor.getLinearGradient(
                            lastX, lastY, lastX + itemWidth * mSize, lastY,
                            colorList
                        )
                    },
                    hoverable : false
                };
                lastX += itemWidth * mSize + this._textGap;
            }
            else {
                itemShape = {
                    zlevel: this.getZlevelBase(),
                    z: this.getZBase(),
                    style : {
                        x : lastX,
                        y : lastY,
                        width : itemWidth,
                        height : itemHeight * mSize,
                        color : zrColor.getLinearGradient(
                            lastX, lastY, lastX, lastY + itemHeight * mSize,
                            colorList
                        )
                    },
                    hoverable : false
                };
                lastY += itemHeight * mSize + this._textGap;
            }
            this.shapeList.push(new RectangleShape(itemShape));
            // 可计算元素的位置缓存
            this._calculableLocation = itemShape.style;
            if (this.dataRangeOption.calculable) {
                this._buildFiller();
                this._bulidMask();
                this._bulidHandle();
            }
            this._buildIndicator();
            
            if (!needValueText && this.dataRangeOption.text[1]) {
                // 最后一个文字
                textShape = this._getTextShape(
                    lastX, lastY, this.dataRangeOption.text[1]
                );

                this.shapeList.push(new TextShape(textShape));
            }
        },
        
        /**
         * 构建指示器 
         */
        _buildIndicator : function() {
            var x = this._calculableLocation.x;
            var y = this._calculableLocation.y;
            var width = this._calculableLocation.width;
            var height = this._calculableLocation.height;
            
            var size = 5;
            var pointList;
            var textPosition;
            if (this.dataRangeOption.orient == 'horizontal') {
                // 水平
                if (this.dataRangeOption.y != 'bottom') {
                    // 手柄统统在下方
                    pointList = [
                        [x, y + height],
                        [x - size, y + height + size],
                        [x + size, y + height + size]
                    ];
                    textPosition = 'bottom';
                }
                else {
                    // 手柄在上方
                    pointList = [
                        [x, y],
                        [x - size, y - size],
                        [x + size, y - size]
                    ];
                    textPosition = 'top';
                }
            }
            else {
                // 垂直
                if (this.dataRangeOption.x != 'right') {
                    // 手柄统统在右侧
                    pointList = [
                        [x + width, y],
                        [x + width + size, y - size],
                        [x + width + size, y + size]
                    ];
                    textPosition = 'right';
                }
                else {
                    // 手柄在左侧
                    pointList = [
                        [x, y],
                        [x - size, y - size],
                        [x - size, y + size]
                    ];
                    textPosition = 'left';
                }
            }
            this._indicatorShape = {
                style : {
                    pointList : pointList,
                    color : '#fff',
                    __rect : {
                        x : Math.min(pointList[0][0], pointList[1][0]),
                        y : Math.min(pointList[0][1], pointList[1][1]),
                        width : size * (this.dataRangeOption.orient == 'horizontal' ? 2 : 1),
                        height : size * (this.dataRangeOption.orient == 'horizontal' ? 1 : 2)
                    }
                },
                highlightStyle : {
                    brushType : 'fill',
                    textPosition : textPosition,
                    textColor : this.dataRangeOption.textStyle.color
                },
                hoverable: false
            };
            this._indicatorShape = new HandlePolygonShape(this._indicatorShape);
        },
        
        /**
         * 构建填充物
         */
        _buildFiller : function () {
            this._fillerShape = {
                zlevel: this.getZlevelBase(),
                z: this.getZBase() + 1,
                style : {
                    x : this._calculableLocation.x,
                    y : this._calculableLocation.y,
                    width : this._calculableLocation.width,
                    height : this._calculableLocation.height,
                    color : 'rgba(255,255,255,0)'
                },
                highlightStyle : {
                    strokeColor : 'rgba(255,255,255,0.5)',
                    lineWidth : 1
                },
                draggable : true,
                ondrift : this._ondrift,
                ondragend : this._ondragend,
                onmousemove : this._dispatchHoverLink,
                _type : 'filler'
            };
            this._fillerShape = new RectangleShape(this._fillerShape);
            this.shapeList.push(this._fillerShape);
        },
        
        /**
         * 构建拖拽手柄
         */
        _bulidHandle : function () {
            var x = this._calculableLocation.x;
            var y = this._calculableLocation.y;
            var width = this._calculableLocation.width;
            var height = this._calculableLocation.height;
            
            var font = this.getFont(this.dataRangeOption.textStyle);
            var textHeight = zrArea.getTextHeight('国', font);
            var textWidth = Math.max(
                    zrArea.getTextWidth(this._textFormat(this.dataRangeOption.max), font),
                    zrArea.getTextWidth(this._textFormat(this.dataRangeOption.min), font)
                ) + 2;
            
            var pointListStart;
            var textXStart;
            var textYStart;
            var coverRectStart;
            var pointListEnd;
            var textXEnd;
            var textYEnd;
            var coverRectEnd;
            if (this.dataRangeOption.orient == 'horizontal') {
                // 水平
                if (this.dataRangeOption.y != 'bottom') {
                    // 手柄统统在下方
                    pointListStart = [
                        [x, y],
                        [x, y + height + textHeight],
                        [x - textHeight, y + height + textHeight],
                        [x - 1, y + height],
                        [x - 1, y]
                        
                    ];
                    textXStart = x - textWidth / 2 - textHeight;
                    textYStart = y + height + textHeight / 2 + 2;
                    coverRectStart = {
                        x : x - textWidth - textHeight,
                        y : y + height,
                        width : textWidth + textHeight,
                        height : textHeight
                    };
                    
                    pointListEnd = [
                        [x + width, y],
                        [x + width, y + height + textHeight],
                        [x + width + textHeight, y + height + textHeight],
                        [x + width + 1, y + height],
                        [x + width + 1, y]
                    ];
                    textXEnd = x + width + textWidth / 2 + textHeight;
                    textYEnd = textYStart;
                    coverRectEnd = {
                        x : x + width,
                        y : y + height,
                        width : textWidth + textHeight,
                        height : textHeight
                    };
                }
                else {
                    // 手柄在上方
                    pointListStart = [
                        [x, y + height],
                        [x, y - textHeight],
                        [x - textHeight, y - textHeight],
                        [x - 1, y],
                        [x - 1, y + height]
                        
                    ];
                    textXStart = x - textWidth / 2 - textHeight;
                    textYStart = y - textHeight / 2 - 2;
                    coverRectStart = {
                        x : x - textWidth - textHeight,
                        y : y - textHeight,
                        width : textWidth + textHeight,
                        height : textHeight
                    };
                    
                    pointListEnd = [
                        [x + width, y + height],
                        [x + width, y - textHeight],
                        [x + width + textHeight, y - textHeight],
                        [x + width + 1, y],
                        [x + width + 1, y + height]
                    ];
                    textXEnd = x + width + textWidth / 2 + textHeight;
                    textYEnd = textYStart;
                    coverRectEnd = {
                        x : x + width,
                        y : y - textHeight,
                        width : textWidth + textHeight,
                        height : textHeight
                    };
                }
            }
            else {
                textWidth += textHeight;
                // 垂直
                if (this.dataRangeOption.x != 'right') {
                    // 手柄统统在右侧
                    pointListStart = [
                        [x, y],
                        [x + width + textHeight, y],
                        [x + width + textHeight, y - textHeight],
                        [x + width, y - 1],
                        [x, y - 1]
                    ];
                    textXStart = x + width + textWidth / 2 + textHeight / 2;
                    textYStart = y - textHeight / 2;
                    coverRectStart = {
                        x : x + width,
                        y : y - textHeight,
                        width : textWidth + textHeight,
                        height : textHeight
                    };
                    
                    pointListEnd = [
                        [x, y + height],
                        [x + width + textHeight, y + height],
                        [x + width + textHeight, y + textHeight + height],
                        [x + width, y + 1 + height],
                        [x, y + height + 1]
                    ];
                    textXEnd = textXStart;
                    textYEnd = y  + height + textHeight / 2;
                    coverRectEnd = {
                        x : x + width,
                        y : y + height,
                        width : textWidth + textHeight,
                        height : textHeight
                    };
                }
                else {
                    // 手柄在左侧
                    pointListStart = [
                        [x + width, y],
                        [x - textHeight, y],
                        [x - textHeight, y - textHeight],
                        [x, y - 1],
                        [x + width, y - 1]
                    ];
                    textXStart = x - textWidth / 2 - textHeight / 2;
                    textYStart = y - textHeight / 2;
                    coverRectStart = {
                        x : x - textWidth - textHeight,
                        y : y - textHeight,
                        width : textWidth + textHeight,
                        height : textHeight
                    };
                    
                    pointListEnd = [
                        [x + width, y + height],
                        [x - textHeight, y + height],
                        [x - textHeight, y + textHeight + height],
                        [x, y + 1 + height],
                        [x + width, y + height + 1]
                    ];
                    textXEnd = textXStart;
                    textYEnd = y  + height + textHeight / 2;
                    coverRectEnd = {
                        x : x - textWidth - textHeight,
                        y : y + height,
                        width : textWidth + textHeight,
                        height : textHeight
                    };
                }
            }
            
            this._startShape = {
                style : {
                    pointList : pointListStart,
                    text : this._textFormat(this.dataRangeOption.max),
                    textX : textXStart,
                    textY : textYStart,
                    textFont: font,
                    color : this.getColor(this.dataRangeOption.max),
                    rect : coverRectStart,
                    x : pointListStart[0][0],
                    y : pointListStart[0][1],
                    _x : pointListStart[0][0],   // 拖拽区域控制缓存
                    _y : pointListStart[0][1]
                }
            };
            this._startShape.highlightStyle = {
                strokeColor : this._startShape.style.color,
                lineWidth : 1
            };
            
            this._endShape = {
                style : {
                    pointList : pointListEnd,
                    text : this._textFormat(this.dataRangeOption.min),
                    textX : textXEnd,
                    textY : textYEnd,
                    textFont: font,
                    color : this.getColor(this.dataRangeOption.min),
                    rect : coverRectEnd,
                    x : pointListEnd[0][0],
                    y : pointListEnd[0][1],
                    _x : pointListEnd[0][0],   // 拖拽区域控制缓存
                    _y : pointListEnd[0][1]
                }
            };
            this._endShape.highlightStyle = {
                strokeColor : this._endShape.style.color,
                lineWidth : 1
            };
            
            // 统一参数
            this._startShape.zlevel              = this._endShape.zlevel    = this.getZlevelBase();
            this._startShape.z                   = this._endShape.z         = this.getZBase() + 1;
            this._startShape.draggable           = this._endShape.draggable = true;
            this._startShape.ondrift             = this._endShape.ondrift   = this._ondrift;
            this._startShape.ondragend           = this._endShape.ondragend = this._ondragend;
            
            this._startShape.style.textColor     = this._endShape.style.textColor 
                                                            = this.dataRangeOption.textStyle.color;
            this._startShape.style.textAlign     = this._endShape.style.textAlign     = 'center';
            this._startShape.style.textPosition  = this._endShape.style.textPosition  = 'specific';
            this._startShape.style.textBaseline  = this._endShape.style.textBaseline  = 'middle';
            // for ondrif计算统一
            this._startShape.style.width         = this._endShape.style.width         = 0; 
            this._startShape.style.height        = this._endShape.style.height        = 0;
            this._startShape.style.textPosition  = this._endShape.style.textPosition  = 'specific';
            
            this._startShape = new HandlePolygonShape(this._startShape);
            this._endShape = new HandlePolygonShape(this._endShape);
            this.shapeList.push(this._startShape);
            this.shapeList.push(this._endShape);
        },
        
        _bulidMask : function () {
            var x = this._calculableLocation.x;
            var y = this._calculableLocation.y;
            var width = this._calculableLocation.width;
            var height = this._calculableLocation.height;
            this._startMask = {
                zlevel: this.getZlevelBase(),
                z: this.getZBase() + 1,
                style : {
                    x : x,
                    y : y,
                    width : this.dataRangeOption.orient == 'horizontal'
                            ? 0 : width,
                    height : this.dataRangeOption.orient == 'horizontal'
                             ? height : 0,
                    color : '#ccc'
                },
                hoverable:false
            };
            this._endMask = {
                zlevel: this.getZlevelBase(),
                z: this.getZBase() + 1,
                style : {
                    x : this.dataRangeOption.orient == 'horizontal'
                        ? x + width : x,
                    y : this.dataRangeOption.orient == 'horizontal'
                        ? y : y + height,
                    width : this.dataRangeOption.orient == 'horizontal'
                            ? 0 : width,
                    height : this.dataRangeOption.orient == 'horizontal'
                             ? height : 0,
                    color : '#ccc'
                },
                hoverable:false
            };
            this._startMask = new RectangleShape(this._startMask);
            this._endMask = new RectangleShape(this._endMask);
            this.shapeList.push(this._startMask);
            this.shapeList.push(this._endMask);
        },
        
        _buildBackground : function () {
            var padding = this.reformCssArray(this.dataRangeOption.padding);
            
            this.shapeList.push(new RectangleShape({
                zlevel: this.getZlevelBase(),
                z: this.getZBase(),
                hoverable :false,
                style : {
                    x : this._itemGroupLocation.x - padding[3],
                    y : this._itemGroupLocation.y - padding[0],
                    width : this._itemGroupLocation.width + padding[3] + padding[1],
                    height : this._itemGroupLocation.height + padding[0] + padding[2],
                    brushType : this.dataRangeOption.borderWidth === 0
                                ? 'fill' : 'both',
                    color : this.dataRangeOption.backgroundColor,
                    strokeColor : this.dataRangeOption.borderColor,
                    lineWidth : this.dataRangeOption.borderWidth
                }
            }));
        },

        /**
         * 根据选项计算值域实体的位置坐标
         */
        _getItemGroupLocation : function () {
            var data = this._valueTextList;
            var dataLength = data.length;
            var itemGap = this.dataRangeOption.itemGap;
            var itemWidth = this.dataRangeOption.itemWidth;
            var itemHeight = this.dataRangeOption.itemHeight;
            var totalWidth = 0;
            var totalHeight = 0;
            var font = this.getFont(this.dataRangeOption.textStyle);
            var textHeight = zrArea.getTextHeight('国', font);
            var mSize = 10;

            if (this.dataRangeOption.orient == 'horizontal') {
                // 水平布局,计算总宽度
                if (this.dataRangeOption.text 
                    || this.dataRangeOption.splitNumber <= 0
                    || this.dataRangeOption.calculable
                ) {
                    // 指定文字或线性渐变
                    totalWidth = 
                        ((this.dataRangeOption.splitNumber <= 0
                          || this.dataRangeOption.calculable)
                          ? (itemWidth * mSize + itemGap)
                          : dataLength * (itemWidth + itemGap))
                        + (this.dataRangeOption.text 
                           && typeof this.dataRangeOption.text[0] != 'undefined'
                           ? (zrArea.getTextWidth(
                                  this.dataRangeOption.text[0],
                                  font
                              ) + this._textGap)
                           : 0)
                        + (this.dataRangeOption.text
                           && typeof this.dataRangeOption.text[1] != 'undefined'
                           ? (zrArea.getTextWidth(
                                  this.dataRangeOption.text[1],
                                  font
                              ) + this._textGap)
                           : 0);
                }
                else {
                    // 值标签
                    itemWidth += 5;
                    for (var i = 0; i < dataLength; i++) {
                        totalWidth += itemWidth
                                      + zrArea.getTextWidth(
                                            data[i],
                                            font
                                        )
                                      + itemGap;
                    }
                }
                totalWidth -= itemGap;      // 减去最后一个的itemGap
                totalHeight = Math.max(textHeight, itemHeight);
            }
            else {
                // 垂直布局,计算总高度
                var maxWidth;
                if (this.dataRangeOption.text
                    || this.dataRangeOption.splitNumber <= 0
                    || this.dataRangeOption.calculable
                ) {
                    // 指定文字或线性渐变
                    totalHeight =
                        ((this.dataRangeOption.splitNumber <= 0
                          || this.dataRangeOption.calculable)
                          ? (itemHeight * mSize + itemGap)
                          : dataLength * (itemHeight + itemGap))
                        + (this.dataRangeOption.text
                           && typeof this.dataRangeOption.text[0] != 'undefined'
                            ? (this._textGap + textHeight)
                            : 0)
                        + (this.dataRangeOption.text
                           && typeof this.dataRangeOption.text[1] != 'undefined'
                            ? (this._textGap + textHeight)
                            : 0);
                       
                    maxWidth = Math.max(
                        zrArea.getTextWidth(
                            (this.dataRangeOption.text && this.dataRangeOption.text[0])
                            || '',
                            font
                        ),
                        zrArea.getTextWidth(
                            (this.dataRangeOption.text && this.dataRangeOption.text[1])
                            || '',
                            font
                        )
                    );
                    totalWidth = Math.max(itemWidth, maxWidth);
                }
                else {
                    totalHeight = (itemHeight + itemGap) * dataLength;
                    // 值标签
                    itemWidth += 5;
                    maxWidth = 0;
                    for (var i = 0; i < dataLength; i++) {
                        maxWidth = Math.max(
                            maxWidth,
                            zrArea.getTextWidth(
                                data[i],
                                font
                            )
                        );
                    }
                    totalWidth = itemWidth + maxWidth;
                }
                totalHeight -= itemGap;     // 减去最后一个的itemGap;
            }

            var padding = this.reformCssArray(this.dataRangeOption.padding);
            var x;
            var zrWidth = this.zr.getWidth();
            switch (this.dataRangeOption.x) {
                case 'center' :
                    x = Math.floor((zrWidth - totalWidth) / 2);
                    break;
                case 'left' :
                    x = padding[3] + this.dataRangeOption.borderWidth;
                    break;
                case 'right' :
                    x = zrWidth
                        - totalWidth
                        - padding[1]
                        - this.dataRangeOption.borderWidth;
                    break;
                default :
                    x = this.parsePercent(this.dataRangeOption.x, zrWidth);
                    x = isNaN(x) ? 0 : x;
                    break;
            }

            var y;
            var zrHeight = this.zr.getHeight();
            switch (this.dataRangeOption.y) {
                case 'top' :
                    y = padding[0] + this.dataRangeOption.borderWidth;
                    break;
                case 'bottom' :
                    y = zrHeight
                        - totalHeight
                        - padding[2]
                        - this.dataRangeOption.borderWidth;
                    break;
                case 'center' :
                    y = Math.floor((zrHeight - totalHeight) / 2);
                    break;
                default :
                    y = this.parsePercent(this.dataRangeOption.y, zrHeight);
                    y = isNaN(y) ? 0 : y;
                    break;
            }
            
            if (this.dataRangeOption.calculable) {
                // 留出手柄控件
                var handlerWidth = Math.max(
                    zrArea.getTextWidth(this.dataRangeOption.max, font),
                    zrArea.getTextWidth(this.dataRangeOption.min, font)
                ) + textHeight;
                if (this.dataRangeOption.orient == 'horizontal') {
                    if (x < handlerWidth) {
                        x = handlerWidth;
                    }
                    if (x + totalWidth + handlerWidth > zrWidth) {
                        x -= handlerWidth;
                    }
                }
                else {
                    if (y < textHeight) {
                        y = textHeight;
                    }
                    if (y + totalHeight + textHeight > zrHeight) {
                        y -= textHeight;
                    }
                }
            }

            return {
                x : x,
                y : y,
                width : totalWidth,
                height : totalHeight
            };
        },

        // 指定文本
        _getTextShape : function (x, y, text) {
            return {
                zlevel: this.getZlevelBase(),
                z: this.getZBase(),
                style : {
                    x : (this.dataRangeOption.orient == 'horizontal'
                        ? x
                        : this._itemGroupLocation.x 
                          + this._itemGroupLocation.width / 2 
                        ),
                    y : (this.dataRangeOption.orient == 'horizontal'
                        ? this._itemGroupLocation.y 
                          + this._itemGroupLocation.height / 2
                        : y
                        ),
                    color : this.dataRangeOption.textStyle.color,
                    text: text,
                    textFont: this.getFont(this.dataRangeOption.textStyle),
                    textBaseline: (this.dataRangeOption.orient == 'horizontal'
                                   ? 'middle' : 'top'),
                    textAlign: (this.dataRangeOption.orient == 'horizontal'
                               ? 'left' : 'center')
                },
                hoverable : false
            };
        },

        // 色尺legend item shape
        _getItemShape : function (x, y, width, height, color) {
            return {
                zlevel: this.getZlevelBase(),
                z: this.getZBase(),
                style : {
                    x : x,
                    y : y + 1,
                    width : width,
                    height : height - 2,
                    color : color
                },
                highlightStyle: {
                    strokeColor: color,
                    lineWidth : 1
                }
            };
        },
        
        /**
         * 拖拽范围控制
         */
        __ondrift : function (shape, dx, dy) {
            var x = this._calculableLocation.x;
            var y = this._calculableLocation.y;
            var width = this._calculableLocation.width;
            var height = this._calculableLocation.height;
            
            if (this.dataRangeOption.orient == 'horizontal') {
                if (shape.style.x + dx <= x) {
                    shape.style.x = x;
                }
                else if (shape.style.x + dx + shape.style.width >= x + width) {
                    shape.style.x = x + width - shape.style.width;
                }
                else {
                    shape.style.x += dx;
                }
            }
            else {
                if (shape.style.y + dy <= y) {
                    shape.style.y = y;
                }
                else if (shape.style.y + dy + shape.style.height >= y + height) {
                    shape.style.y = y + height - shape.style.height;
                }
                else {
                    shape.style.y += dy;
                }
            }

            if (shape._type == 'filler') {
                this._syncHandleShape();
            }
            else {
                this._syncFillerShape(shape);
            }
            
            if (this.dataRangeOption.realtime) {
                this._dispatchDataRange();
            }

            return true;
        },
        
        __ondragend : function () {
            this.isDragend = true;
        },
        
        /**
         * 数据项被拖拽出去
         */
        ondragend : function (param, status) {
            if (!this.isDragend || !param.target) {
                // 没有在当前实例上发生拖拽行为则直接返回
                return;
            }

            // 别status = {}赋值啊!!
            status.dragOut = true;
            status.dragIn = true;
            
            if (!this.dataRangeOption.realtime) {
                this._dispatchDataRange();
            }
            
            status.needRefresh = false; // 会有消息触发fresh,不用再刷一遍
            // 处理完拖拽事件后复位
            this.isDragend = false;

            return;
        },
        
        // 外部传入range
        _syncShapeFromRange : function () {
            var range = this.dataRangeOption.range || {};
            // 做一个反转
            this._range.end = typeof this._range.end != 'undefined'
                              ? this._range.end
                              : (typeof range.start != 'undefined' ? range.start : 0);
            this._range.start = typeof this._range.start != 'undefined'
                                ? this._range.start
                                : (typeof range.end != 'undefined' ? range.end : 100);
            
            if (this._range.start != 100 || this._range.end !== 0) {
                // 非默认满值同步一下图形
                if (this.dataRangeOption.orient == 'horizontal') {
                    // 横向
                    var width = this._fillerShape.style.width;
                    this._fillerShape.style.x +=
                        width * (100 - this._range.start) / 100;
                    this._fillerShape.style.width = 
                        width * (this._range.start - this._range.end) / 100;
                }
                else {
                    // 纵向
                    var height = this._fillerShape.style.height;
                    this._fillerShape.style.y +=
                        height * (100 - this._range.start) / 100;
                    this._fillerShape.style.height = 
                        height * (this._range.start - this._range.end) / 100;
                }
                this.zr.modShape(this._fillerShape.id);
                this._syncHandleShape();
            }
        },
        
        _syncHandleShape : function () {
            var x = this._calculableLocation.x;
            var y = this._calculableLocation.y;
            var width = this._calculableLocation.width;
            var height = this._calculableLocation.height;
            
            if (this.dataRangeOption.orient == 'horizontal') {
                this._startShape.style.x = this._fillerShape.style.x;
                this._startMask.style.width = this._startShape.style.x - x;
                
                this._endShape.style.x = this._fillerShape.style.x
                                    + this._fillerShape.style.width;
                this._endMask.style.x = this._endShape.style.x;
                this._endMask.style.width = x + width - this._endShape.style.x;
                
                this._range.start = Math.ceil(
                    100 - (this._startShape.style.x - x) / width * 100
                );
                this._range.end = Math.floor(
                    100 - (this._endShape.style.x - x) / width * 100
                );
            }
            else {
                this._startShape.style.y = this._fillerShape.style.y;
                this._startMask.style.height = this._startShape.style.y - y;
                
                this._endShape.style.y = this._fillerShape.style.y
                                    + this._fillerShape.style.height;
                this._endMask.style.y = this._endShape.style.y;
                this._endMask.style.height = y + height - this._endShape.style.y;
                
                this._range.start = Math.ceil(
                    100 - (this._startShape.style.y - y) / height * 100
                );
                this._range.end = Math.floor(
                    100 - (this._endShape.style.y - y) / height * 100
                );
            }
            
            this._syncShape();
        },

        _syncFillerShape : function (e) {
            var x = this._calculableLocation.x;
            var y = this._calculableLocation.y;
            var width = this._calculableLocation.width;
            var height = this._calculableLocation.height;
            
            var a;
            var b;
            if (this.dataRangeOption.orient == 'horizontal') {
                a = this._startShape.style.x;
                b = this._endShape.style.x;
                if (e.id == this._startShape.id && a >= b) {
                    // _startShape触发
                    b = a;
                    this._endShape.style.x = a;
                }
                else if (e.id == this._endShape.id && a >= b) {
                    // _endShape触发
                    a = b;
                    this._startShape.style.x = a;
                }
                this._fillerShape.style.x = a;
                this._fillerShape.style.width = b - a;
                this._startMask.style.width = a - x;
                this._endMask.style.x = b;
                this._endMask.style.width = x + width - b;
                
                this._range.start = Math.ceil(100 - (a - x) / width * 100);
                this._range.end = Math.floor(100 - (b - x) / width * 100);
            }
            else {
                a = this._startShape.style.y;
                b = this._endShape.style.y;
                if (e.id == this._startShape.id && a >= b) {
                    // _startShape触发
                    b = a;
                    this._endShape.style.y = a;
                }
                else if (e.id == this._endShape.id && a >= b) {
                    // _endShape触发
                    a = b;
                    this._startShape.style.y = a;
                }
                this._fillerShape.style.y = a;
                this._fillerShape.style.height = b - a;
                this._startMask.style.height = a - y;
                this._endMask.style.y = b;
                this._endMask.style.height = y + height - b;
                
                this._range.start = Math.ceil(100 - (a - y) / height * 100);
                this._range.end = Math.floor(100 - (b - y) / height * 100);
            }
            
            this._syncShape();
        },
        
        _syncShape : function () {
            this._startShape.position = [
                this._startShape.style.x - this._startShape.style._x,
                this._startShape.style.y - this._startShape.style._y
            ];
            
            this._startShape.style.text = this._textFormat(
                this._gap * this._range.start + this.dataRangeOption.min
            );
            
            this._startShape.style.color 
                = this._startShape.highlightStyle.strokeColor
                = this.getColor(
                    this._gap * this._range.start + this.dataRangeOption.min
                );
            
            this._endShape.position = [
                this._endShape.style.x - this._endShape.style._x,
                this._endShape.style.y - this._endShape.style._y
            ];
            
            this._endShape.style.text = this._textFormat(
                this._gap * this._range.end + this.dataRangeOption.min
            );
            
            this._endShape.style.color 
                = this._endShape.highlightStyle.strokeColor 
                = this.getColor(
                    this._gap * this._range.end + this.dataRangeOption.min
                );
            
            this.zr.modShape(this._startShape.id);
            this.zr.modShape(this._endShape.id);
            this.zr.modShape(this._startMask.id);
            this.zr.modShape(this._endMask.id);
            this.zr.modShape(this._fillerShape.id);
            this.zr.refreshNextFrame();
        },

        _dispatchDataRange : function () {
            this.messageCenter.dispatch(
                ecConfig.EVENT.DATA_RANGE,
                null,
                {
                    range : {
                        start : this._range.end,
                        end : this._range.start
                    }
                },
                this.myChart
            );
        },


        __dataRangeSelected : function (param) {
            if (this.dataRangeOption.selectedMode === 'single') {
                for (var k in this._selectedMap) {
                    this._selectedMap[k] = false;
                }
            }
            var idx = param.target._idx;
            this._selectedMap[idx] = !this._selectedMap[idx];
            var valueMax = (this._colorList.length - idx) * this._gap + this.dataRangeOption.min;
            this.messageCenter.dispatch(
                ecConfig.EVENT.DATA_RANGE_SELECTED,
                param.event,
                {
                    selected: this._selectedMap,
                    target: idx,
                    valueMax: valueMax,
                    valueMin: valueMax - this._gap
                },
                this.myChart
            );

            this.messageCenter.dispatch(ecConfig.EVENT.REFRESH, null, null, this.myChart);
        },
        
        /**
         * 产生hover link事件 
         */
        __dispatchHoverLink : function(param) {
            var valueMin;
            var valueMax;
            if (this.dataRangeOption.calculable) {
                var totalValue = this.dataRangeOption.max - this.dataRangeOption.min;
                var curValue;
                if (this.dataRangeOption.orient == 'horizontal') {
                    curValue = (1 - (zrEvent.getX(param.event) - this._calculableLocation.x)
                               / this._calculableLocation.width)
                               * totalValue;
                }
                else {
                    curValue = (1 - (zrEvent.getY(param.event) - this._calculableLocation.y)
                               / this._calculableLocation.height) 
                               * totalValue;
                }
                valueMin = curValue - totalValue * 0.05;
                valueMax = curValue + totalValue * 0.05;
            }
            else {
                var idx = param.target._idx;
                valueMax = (this._colorList.length - idx) * this._gap + this.dataRangeOption.min;
                valueMin = valueMax - this._gap;
            }
            
            this.messageCenter.dispatch(
                ecConfig.EVENT.DATA_RANGE_HOVERLINK, 
                param.event,
                {
                    valueMin : valueMin,
                    valueMax : valueMax
                },
                this.myChart
            );
            
            // console.log(param,curValue);
            return;
        },
        
        __onhoverlink: function(param) {
            if (this.dataRangeOption.show
                && this.dataRangeOption.hoverLink
                && this._indicatorShape
                && param 
                && param.seriesIndex != null && param.dataIndex != null
            ) {
                var curValue = param.value;
                if (curValue === '' || isNaN(curValue)) {
                    return;
                }
                if (curValue < this.dataRangeOption.min) {
                    curValue = this.dataRangeOption.min;
                }
                else if (curValue > this.dataRangeOption.max) {
                    curValue = this.dataRangeOption.max;
                }
                
                if (this.dataRangeOption.orient == 'horizontal') {
                    this._indicatorShape.position = [
                        (this.dataRangeOption.max - curValue) 
                        / (this.dataRangeOption.max - this.dataRangeOption.min)
                        * this._calculableLocation.width,
                        0
                    ];
                }
                else {
                    this._indicatorShape.position = [
                        0,
                        (this.dataRangeOption.max - curValue)
                        / (this.dataRangeOption.max - this.dataRangeOption.min)
                        * this._calculableLocation.height
                    ];
                }
                this._indicatorShape.style.text = this._textFormat(param.value);
                this._indicatorShape.style.color = this.getColor(curValue);
                this.zr.addHoverShape(this._indicatorShape);
            }
        },

        _textFormat : function(valueStart, valueEnd) {
            valueStart = (+valueStart).toFixed(this.dataRangeOption.precision);
            valueEnd = valueEnd != null ? (+valueEnd).toFixed(this.dataRangeOption.precision) : '';
            if (this.dataRangeOption.formatter) {
                if (typeof this.dataRangeOption.formatter == 'string') {
                    return this.dataRangeOption.formatter.replace('{value}', valueStart)
                                                         .replace('{value2}', valueEnd);
                }
                else if (typeof this.dataRangeOption.formatter == 'function') {
                    return this.dataRangeOption.formatter.call(
                        this.myChart, valueStart, valueEnd
                    );
                }
            }
            
            if (valueEnd !== '') {
                return valueStart + ' - ' + valueEnd;
            }

            return valueStart;
        },
        
        /**
         * 刷新
         */
        refresh : function (newOption) {
            if (newOption) {
                this.option = newOption;
                this.option.dataRange = this.reformOption(this.option.dataRange);
                this.dataRangeOption = this.option.dataRange;
                if (!this.myChart.canvasSupported) {
                    // 不支持Canvas的强制关闭实时动画
                    this.dataRangeOption.realtime = false;
                }
                
                var splitNumber = this.dataRangeOption.splitNumber <= 0 
                                  || this.dataRangeOption.calculable
                                  ? 100
                                  : this.dataRangeOption.splitNumber;
                this._colorList = zrColor.getGradientColors(
                    this.dataRangeOption.color,
                    Math.max(
                        (splitNumber - this.dataRangeOption.color.length)
                        / (this.dataRangeOption.color.length - 1),
                        0
                    ) + 1
                );
                
                if (this._colorList.length > splitNumber) {
                    var len = this._colorList.length;
                    var newColorList = [this._colorList[0]];
                    var step = len / (splitNumber - 1);
                    for (var i = 1; i < splitNumber - 1; i++) {
                        newColorList.push(this._colorList[Math.floor(i * step)]);
                    }
                    newColorList.push(this._colorList[len - 1]);
                    this._colorList = newColorList;
                }
                // console.log(this._colorList.length)
                
                var precision = this.dataRangeOption.precision;
                this._gap = (this.dataRangeOption.max - this.dataRangeOption.min) / splitNumber;
                while (this._gap.toFixed(precision) - 0 != this._gap && precision < 5) {
                    // 精度自适应
                    precision++;
                }
                this.dataRangeOption.precision = precision;
                
                this._gap = (
                    (this.dataRangeOption.max - this.dataRangeOption.min) / splitNumber
                ).toFixed(precision) - 0;
                
                this._valueTextList = [];
                for (var i = 0; i < splitNumber; i++) {
                    this._selectedMap[i] = true;
                    this._valueTextList.unshift(
                        this._textFormat(
                            i * this._gap + this.dataRangeOption.min,
                            (i + 1) * this._gap + this.dataRangeOption.min
                        )
                    );
                }
            }
            
            this.clear();
            this._buildShape();
        },

        getColor : function (value) {
            if (isNaN(value)) {
                return null;
            }
            
            if (this.dataRangeOption.min == this.dataRangeOption.max) {
                return this._colorList[0];
            }
            
            if (value < this.dataRangeOption.min) {
                value = this.dataRangeOption.min;
            }
            else if (value > this.dataRangeOption.max) {
                value = this.dataRangeOption.max;
            }
            
            if (this.dataRangeOption.calculable) {
                if (value - (this._gap * this._range.start + this.dataRangeOption.min) > 0.00005
                    || value - (this._gap * this._range.end + this.dataRangeOption.min) < -0.00005) {
                     return null;
                }
            }
            
            var idx = this._colorList.length - Math.ceil(
                (value - this.dataRangeOption.min) 
                / (this.dataRangeOption.max - this.dataRangeOption.min)
                * this._colorList.length
            );
            if (idx == this._colorList.length) {
                idx--;
            }
            
            //console.log(value, idx,this._colorList[idx])
            if (this._selectedMap[idx]) {
                return this._colorList[idx];
            }
            else {
                return null;
            }
            
        },
        
        getColorByIndex : function (idx) {
            if (idx >= this._colorList.length) {
                idx = this._colorList.length - 1;
            }
            else if (idx < 0) {
                idx = 0;
            }
            return this._colorList[idx];
        },
        
        /**
         * 释放后实例不可用
         */
        onbeforDispose : function () {
            this.messageCenter.unbind(ecConfig.EVENT.HOVER, this._onhoverlink);
        }
    };
    
    zrUtil.inherits(DataRange, Base);
    
    require('../component').define('dataRange', DataRange);

    return DataRange;
});