/**
 * echarts图表类：饼图
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *
 */
define(function (require) {
    var ChartBase = require('./base');

    // 图形依赖
    var TextShape = require('zrender/shape/Text');
    var RingShape = require('zrender/shape/Ring');
    var CircleShape = require('zrender/shape/Circle');
    var SectorShape = require('zrender/shape/Sector');
    var PolylineShape = require('zrender/shape/Polyline');

    var ecConfig = require('../config');
    // 饼图默认参数
    ecConfig.pie = {
        zlevel: 0,                  // 一级层叠
        z: 2,                       // 二级层叠
        clickable: true,
        legendHoverLink: true,
        center: ['50%', '50%'],     // 默认全局居中
        radius: [0, '75%'],
        clockWise: true,            // 默认顺时针
        startAngle: 90,
        minAngle: 0,                // 最小角度改为0
        selectedOffset: 10,         // 选中是扇区偏移量
        // selectedMode: false,     // 选择模式，默认关闭，可选single，multiple
        // roseType: null,          // 南丁格尔玫瑰图模式，'radius'（半径） | 'area'（面积）
        itemStyle: {
            normal: {
                // color: 各异,
                borderColor: 'rgba(0,0,0,0)',
                borderWidth: 1,
                label: {
                    show: true,
                    position: 'outer'
                    // formatter: 标签文本格式器，同Tooltip.formatter，不支持异步回调
                    // textStyle: null      // 默认使用全局文本样式，详见TEXTSTYLE
                    // distance: 当position为inner时有效，为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数
                },
                labelLine: {
                    show: true,
                    length: 20,
                    lineStyle: {
                        // color: 各异,
                        width: 1,
                        type: 'solid'
                    }
                }
            },
            emphasis: {
                // color: 各异,
                borderColor: 'rgba(0,0,0,0)',
                borderWidth: 1,
                label: {
                    show: false
                    // position: 'outer'
                    // formatter: 标签文本格式器，同Tooltip.formatter，不支持异步回调
                    // textStyle: null      // 默认使用全局文本样式，详见TEXTSTYLE
                    // distance: 当position为inner时有效，为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数
                },
                labelLine: {
                    show: false,
                    length: 20,
                    lineStyle: {
                        // color: 各异,
                        width: 1,
                        type: 'solid'
                    }
                }
            }
        }
    };

    var ecData = require('../util/ecData');
    var zrUtil = require('zrender/tool/util');
    var zrMath = require('zrender/tool/math');
    var zrColor = require('zrender/tool/color');

    /**
     * 构造函数
     * @param {Object} messageCenter echart消息中心
     * @param {ZRender} zr zrender实例
     * @param {Object} series 数据
     * @param {Object} component 组件
     */
    function Pie(ecTheme, messageCenter, zr, option, myChart){
        // 图表基类
        ChartBase.call(this, ecTheme, messageCenter, zr, option, myChart);

        var self = this;
        /**
         * 输出动态视觉引导线
         */
        self.shapeHandler.onmouseover = function (param) {
            var shape = param.target;
            var seriesIndex = ecData.get(shape, 'seriesIndex');
            var dataIndex = ecData.get(shape, 'dataIndex');
            var percent = ecData.get(shape, 'special');

            var center = [shape.style.x, shape.style.y];
            var startAngle = shape.style.startAngle;
            var endAngle = shape.style.endAngle;
            var midAngle = ((endAngle + startAngle) / 2 + 360) % 360; // 中值
            var defaultColor = shape.highlightStyle.color;

            // 文本标签，需要显示则会有返回
            var label = self.getLabel(
                    seriesIndex, dataIndex, percent,
                    center, midAngle, defaultColor,
                    true
                );

            if (label) {
                self.zr.addHoverShape(label);
            }

            // 文本标签视觉引导线，需要显示则会有返回
            var labelLine = self.getLabelLine(
                    seriesIndex, dataIndex,
                    center, shape.style.r0, shape.style.r,
                    midAngle, defaultColor,
                    true
                );

            if (labelLine) {
                self.zr.addHoverShape(labelLine);
            }
        };

        this.refresh(option);
    }

    Pie.prototype = {
        type: ecConfig.CHART_TYPE_PIE,
        /**
         * 绘制图形
         */
        _buildShape: function () {
            var series = this.series;
            var legend = this.component.legend;
            this.selectedMap = {};
            this._selected = {};
            var center;
            var radius;

            var pieCase;        // 饼图箱子
            this._selectedMode = false;
            var serieName;
            for (var i = 0, l = series.length; i < l; i++) {
                if (series[i].type === ecConfig.CHART_TYPE_PIE) {
                    series[i] = this.reformOption(series[i]);
                    this.legendHoverLink = series[i].legendHoverLink || this.legendHoverLink;
                    serieName = series[i].name || '';
                    // 系列图例开关
                    this.selectedMap[serieName] = legend ? legend.isSelected(serieName) : true;
                    if (!this.selectedMap[serieName]) {
                        continue;
                    }

                    center = this.parseCenter(this.zr, series[i].center);
                    radius = this.parseRadius(this.zr, series[i].radius);
                    this._selectedMode = this._selectedMode || series[i].selectedMode;
                    this._selected[i] = [];
                    if (this.deepQuery([series[i], this.option], 'calculable')) {
                        pieCase = {
                            zlevel: series[i].zlevel,
                            z: series[i].z,
                            hoverable: false,
                            style: {
                                x: center[0],          // 圆心横坐标
                                y: center[1],          // 圆心纵坐标
                                // 圆环内外半径
                                r0: radius[0] <= 10 ? 0 : radius[0] - 10,
                                r: radius[1] + 10,
                                brushType: 'stroke',
                                lineWidth: 1,
                                strokeColor: series[i].calculableHolderColor
                                             || this.ecTheme.calculableHolderColor
                                             || ecConfig.calculableHolderColor
                            }
                        };
                        ecData.pack(pieCase, series[i], i, undefined, -1);
                        this.setCalculable(pieCase);

                        pieCase = radius[0] <= 10
                                  ? new CircleShape(pieCase)
                                  : new RingShape(pieCase);
                        this.shapeList.push(pieCase);
                    }
                    this._buildSinglePie(i);
                    this.buildMark(i);
                }
            }

            this.addShapeList();
        },

        /**
         * 构建单个饼图
         *
         * @param {number} seriesIndex 系列索引
         */
        _buildSinglePie: function (seriesIndex) {
            var series = this.series;
            var serie = series[seriesIndex];
            var data = serie.data;
            var legend = this.component.legend;
            var itemName;
            var totalSelected = 0;               // 迭代累计选中且非0个数
            var totalSelectedValue0 = 0;         // 迭代累计选中0只个数
            var totalValue = 0;                  // 迭代累计
            var maxValue = Number.NEGATIVE_INFINITY;

            var singleShapeList = [];
            // 计算需要显示的个数和总值
            for (var i = 0, l = data.length; i < l; i++) {
                itemName = data[i].name;
                this.selectedMap[itemName] = legend ? legend.isSelected(itemName) : true;

                if (this.selectedMap[itemName] && !isNaN(data[i].value)) {
                    if (+data[i].value !== 0) {
                        totalSelected++;
                    }
                    else {
                        totalSelectedValue0++;
                    }
                    totalValue += +data[i].value;
                    maxValue = Math.max(maxValue, +data[i].value);
                }
            }

            if (totalValue === 0) {
                return;
            }

            var percent = 100;
            var clockWise = serie.clockWise;
            var startAngle = (serie.startAngle.toFixed(2) - 0 + 360) % 360;
            var endAngle;
            var minAngle = serie.minAngle || 0.01; // #bugfixed
            var totalAngle = 360 - (minAngle * totalSelected) - 0.01 * totalSelectedValue0;
            var defaultColor;
            var roseType = serie.roseType;
            var center;
            var radius;
            var r0;     // 扇形内半径
            var r1;     // 扇形外半径

            for (var i = 0, l = data.length; i < l; i++) {
                itemName = data[i].name;
                if (!this.selectedMap[itemName] || isNaN(data[i].value)) {
                    continue;
                }
                // 默认颜色策略，有图例则从图例中获取颜色定义，没有就全局颜色定义
                defaultColor = legend ? legend.getColor(itemName) : this.zr.getColor(i);

                percent = data[i].value / totalValue;
                if (roseType != 'area') {
                    endAngle = clockWise
                        ? (startAngle - percent * totalAngle - (percent !== 0 ? minAngle : 0.01))
                        : (percent * totalAngle + startAngle + (percent !== 0 ? minAngle : 0.01));
                }
                else {
                    endAngle = clockWise
                        ? (startAngle - 360 / l)
                        : (360 / l + startAngle);
                }
                endAngle = endAngle.toFixed(2) - 0;
                percent = (percent * 100).toFixed(2);

                center = this.parseCenter(this.zr, serie.center);
                radius = this.parseRadius(this.zr, serie.radius);
                r0 = +radius[0];
                r1 = +radius[1];

                if (roseType === 'radius') {
                    r1 = data[i].value / maxValue * (r1 - r0) * 0.8 + (r1 - r0) * 0.2 + r0;
                }
                else if (roseType === 'area') {
                    r1 = Math.sqrt(data[i].value / maxValue) * (r1 - r0) + r0;
                }

                if (clockWise) {
                    var temp;
                    temp = startAngle;
                    startAngle = endAngle;
                    endAngle = temp;
                }

                this._buildItem(
                    singleShapeList,
                    seriesIndex, i, percent,
                    data[i].selected,
                    center, r0, r1,
                    startAngle, endAngle, defaultColor
                );
                if (!clockWise) {
                    startAngle = endAngle;
                }
            }
            this._autoLabelLayout(singleShapeList, center, r1);
            for (var i = 0, l = singleShapeList.length; i < l; i++) {
                this.shapeList.push(singleShapeList[i]);
            }
            singleShapeList = null;
        },

        /**
         * 构建单个扇形及指标
         */
        _buildItem: function (
            singleShapeList,
            seriesIndex, dataIndex, percent,
            isSelected,
            center, r0, r1,
            startAngle, endAngle, defaultColor
        ) {
            var series = this.series;
            var midAngle = ((endAngle + startAngle) / 2 + 360) % 360; // 中值

            // 扇形
            var sector = this.getSector(
                    seriesIndex, dataIndex, percent, isSelected,
                    center, r0, r1,
                    startAngle, endAngle, defaultColor
                );
            // 图形需要附加的私有数据
            ecData.pack(
                sector,
                series[seriesIndex], seriesIndex,
                series[seriesIndex].data[dataIndex], dataIndex,
                series[seriesIndex].data[dataIndex].name,
                percent
            );
            singleShapeList.push(sector);

            // 文本标签，需要显示则会有返回
            var label = this.getLabel(
                    seriesIndex, dataIndex, percent,
                    center, midAngle, defaultColor,
                    false
                );
            // 文本标签视觉引导线，需要显示则会有返回
            var labelLine = this.getLabelLine(
                    seriesIndex, dataIndex,
                    center, r0, r1,
                    midAngle, defaultColor,
                    false
                );

            if (labelLine) {
                ecData.pack(
                    labelLine,
                    series[seriesIndex], seriesIndex,
                    series[seriesIndex].data[dataIndex], dataIndex,
                    series[seriesIndex].data[dataIndex].name,
                    percent
                );
                singleShapeList.push(labelLine);
            }
            if (label) {
                ecData.pack(
                    label,
                    series[seriesIndex], seriesIndex,
                    series[seriesIndex].data[dataIndex], dataIndex,
                    series[seriesIndex].data[dataIndex].name,
                    percent
                );
                label._labelLine = labelLine;
                singleShapeList.push(label);
            }
        },

        /**
         * 构建扇形
         */
        getSector: function (
            seriesIndex, dataIndex, percent, isSelected,
            center, r0, r1,
            startAngle, endAngle, defaultColor
        ) {
            var series = this.series;
            var serie = series[seriesIndex];
            var data = serie.data[dataIndex];
            var queryTarget = [data, serie];

            // 多级控制
            var normal = this.deepMerge(
                queryTarget,
                'itemStyle.normal'
            ) || {};
            var emphasis = this.deepMerge(
                queryTarget,
                'itemStyle.emphasis'
            ) || {};
            var normalColor = this.getItemStyleColor(normal.color, seriesIndex, dataIndex, data)
                              || defaultColor;

            var emphasisColor = this.getItemStyleColor(emphasis.color, seriesIndex, dataIndex, data)
                || (typeof normalColor === 'string'
                    ? zrColor.lift(normalColor, -0.2)
                    : normalColor
                );

            var sector = {
                zlevel: serie.zlevel,
                z: serie.z,
                clickable: this.deepQuery(queryTarget, 'clickable'),
                style: {
                    x: center[0],          // 圆心横坐标
                    y: center[1],          // 圆心纵坐标
                    r0: r0,         // 圆环内半径
                    r: r1,          // 圆环外半径
                    startAngle: startAngle,
                    endAngle: endAngle,
                    brushType: 'both',
                    color: normalColor,
                    lineWidth: normal.borderWidth,
                    strokeColor: normal.borderColor,
                    lineJoin: 'round'
                },
                highlightStyle: {
                    color: emphasisColor,
                    lineWidth: emphasis.borderWidth,
                    strokeColor: emphasis.borderColor,
                    lineJoin: 'round'
                },
                _seriesIndex: seriesIndex,
                _dataIndex: dataIndex
            };

            if (isSelected) {
                var midAngle =
                    ((sector.style.startAngle + sector.style.endAngle) / 2).toFixed(2) - 0;
                sector.style._hasSelected = true;
                sector.style._x = sector.style.x;
                sector.style._y = sector.style.y;
                var offset = this.query(serie, 'selectedOffset');
                sector.style.x += zrMath.cos(midAngle, true) * offset;
                sector.style.y -= zrMath.sin(midAngle, true) * offset;

                this._selected[seriesIndex][dataIndex] = true;
            }
            else {
                this._selected[seriesIndex][dataIndex] = false;
            }


            if (this._selectedMode) {
                sector.onclick = this.shapeHandler.onclick;
            }

            if (this.deepQuery([data, serie, this.option], 'calculable')) {
                this.setCalculable(sector);
                sector.draggable = true;
            }

            // “emphasis显示”添加事件响应
            if (this._needLabel(serie, data, true)          // emphasis下显示文本
                || this._needLabelLine(serie, data, true)   // emphasis下显示引导线
            ) {
                sector.onmouseover = this.shapeHandler.onmouseover;
            }

            sector = new SectorShape(sector);
            return sector;
        },

        /**
         * 需要显示则会有返回构建好的shape，否则返回undefined
         */
        getLabel: function (
            seriesIndex, dataIndex, percent,
            center, midAngle, defaultColor,
            isEmphasis
        ) {
            var series = this.series;
            var serie = series[seriesIndex];
            var data = serie.data[dataIndex];

            // 特定状态下是否需要显示文本标签
            if (!this._needLabel(serie, data, isEmphasis)) {
                return;
            }

            var status = isEmphasis ? 'emphasis' : 'normal';

            // serie里有默认配置，放心大胆的用！
            var itemStyle = zrUtil.merge(
                    zrUtil.clone(data.itemStyle) || {},
                    serie.itemStyle
                );
            // label配置
            var labelControl = itemStyle[status].label;
            var textStyle = labelControl.textStyle || {};

            var centerX = center[0];                      // 圆心横坐标
            var centerY = center[1];                      // 圆心纵坐标
            var x;
            var y;
            var radius = this.parseRadius(this.zr, serie.radius);  // 标签位置半径
            var textAlign;
            var textBaseline = 'middle';
            labelControl.position = labelControl.position
                                    || itemStyle.normal.label.position;
            if (labelControl.position === 'center') {
                // center显示
                x = centerX;
                y = centerY;
                textAlign = 'center';
            }
            else if (labelControl.position === 'inner' || labelControl.position === 'inside') {
                // 内部标签显示, 按外半径比例计算标签位置
                radius = (radius[0] + radius[1]) * (labelControl.distance || 0.5);
                x = Math.round(centerX + radius * zrMath.cos(midAngle, true));
                y = Math.round(centerY - radius * zrMath.sin(midAngle, true));
                defaultColor = '#fff';
                textAlign = 'center';
            }
            else {
                // 外部显示，默认 labelControl.position === 'outer')
                radius = radius[1] - (-itemStyle[status].labelLine.length);
                x = Math.round(centerX + radius * zrMath.cos(midAngle, true));
                y = Math.round(centerY - radius * zrMath.sin(midAngle, true));
                textAlign = (midAngle >= 90 && midAngle <= 270) ? 'right' : 'left';
            }

            if (labelControl.position != 'center'
                && labelControl.position != 'inner'
                && labelControl.position != 'inside'
            ) {
                x += textAlign === 'left' ? 20 : -20;
            }
            data.__labelX = x - (textAlign === 'left' ? 5 : -5);
            data.__labelY = y;

            var ts = new TextShape({
                zlevel: serie.zlevel,
                z: serie.z + 1,
                hoverable: false,
                style: {
                    x: x,
                    y: y,
                    color: textStyle.color || defaultColor,
                    text: this.getLabelText(seriesIndex, dataIndex, percent, status),
                    textAlign: textStyle.align || textAlign,
                    textBaseline: textStyle.baseline || textBaseline,
                    textFont: this.getFont(textStyle)
                },
                highlightStyle: {
                    brushType: 'fill'
                }
            });
            ts._radius = radius;
            ts._labelPosition = labelControl.position || 'outer';
            ts._rect = ts.getRect(ts.style);
            ts._seriesIndex = seriesIndex;
            ts._dataIndex = dataIndex;
            return ts;

        },

        /**
         * 根据lable.format计算label text
         */
        getLabelText: function (seriesIndex, dataIndex, percent, status) {
            var series = this.series;
            var serie = series[seriesIndex];
            var data = serie.data[dataIndex];
            var formatter = this.deepQuery(
                [data, serie],
                'itemStyle.' + status + '.label.formatter'
            );

            if (formatter) {
                if (typeof formatter === 'function') {
                    return formatter.call(
                        this.myChart,
                        {
                            seriesIndex: seriesIndex,
                            seriesName: serie.name || '',
                            series: serie,
                            dataIndex: dataIndex,
                            data: data,
                            name: data.name,
                            value: data.value,
                            percent: percent
                        }
                    );
                }
                else if (typeof formatter === 'string') {
                    formatter = formatter.replace('{a}','{a0}')
                                         .replace('{b}','{b0}')
                                         .replace('{c}','{c0}')
                                         .replace('{d}','{d0}');
                    formatter = formatter.replace('{a0}', serie.name)
                                         .replace('{b0}', data.name)
                                         .replace('{c0}', data.value)
                                         .replace('{d0}', percent);

                    return formatter;
                }
            }
            else {
                return data.name;
            }
        },

        /**
         * 需要显示则会有返回构建好的shape，否则返回undefined
         */
        getLabelLine: function (
            seriesIndex, dataIndex,
            center, r0, r1,
            midAngle, defaultColor,
            isEmphasis
        ) {
            var series = this.series;
            var serie = series[seriesIndex];
            var data = serie.data[dataIndex];

            // 特定状态下是否需要显示文本标签
            if (this._needLabelLine(serie, data, isEmphasis)) {
                var status = isEmphasis ? 'emphasis' : 'normal';

                // serie里有默认配置，放心大胆的用！
                var itemStyle = zrUtil.merge(
                        zrUtil.clone(data.itemStyle) || {},
                        serie.itemStyle
                    );
                // labelLine配置
                var labelLineControl = itemStyle[status].labelLine;
                var lineStyle = labelLineControl.lineStyle || {};

                var centerX = center[0];                    // 圆心横坐标
                var centerY = center[1];                    // 圆心纵坐标
                // 视觉引导线起点半径
                var minRadius = r1;
                // 视觉引导线终点半径
                var maxRadius = this.parseRadius(this.zr, serie.radius)[1]
                                - (-labelLineControl.length);
                var cosValue = zrMath.cos(midAngle, true);
                var sinValue = zrMath.sin(midAngle, true);

                return new PolylineShape({
                    zlevel: serie.zlevel,
                    z: serie.z + 1,
                    hoverable: false,
                    style: {
                        pointList: [
                            [
                                centerX + minRadius * cosValue,
                                centerY - minRadius * sinValue
                            ],
                            [
                                centerX + maxRadius * cosValue,
                                centerY - maxRadius * sinValue
                            ],
                            [
                                data.__labelX,
                                data.__labelY
                            ]
                        ],
                        //xStart: centerX + minRadius * cosValue,
                        //yStart: centerY - minRadius * sinValue,
                        //xEnd: centerX + maxRadius * cosValue,
                        //yEnd: centerY - maxRadius * sinValue,
                        strokeColor: lineStyle.color || defaultColor,
                        lineType: lineStyle.type,
                        lineWidth: lineStyle.width
                    },
                    _seriesIndex: seriesIndex,
                    _dataIndex: dataIndex
                });
            }
            else {
                return;
            }
        },

        /**
         * 返回特定状态（normal or emphasis）下是否需要显示label标签文本
         * @param {Object} serie
         * @param {Object} data
         * @param {boolean} isEmphasis true is 'emphasis' and false is 'normal'
         */
        _needLabel: function (serie, data, isEmphasis) {
            return this.deepQuery(
                [data, serie],
                'itemStyle.'
                + (isEmphasis ? 'emphasis' : 'normal')
                + '.label.show'
            );
        },

        /**
         * 返回特定状态（normal or emphasis）下是否需要显示labelLine标签视觉引导线
         * @param {Object} serie
         * @param {Object} data
         * @param {boolean} isEmphasis true is 'emphasis' and false is 'normal'
         */
        _needLabelLine: function (serie, data, isEmphasis) {
            return this.deepQuery(
                [data, serie],
                'itemStyle.'
                + (isEmphasis ? 'emphasis' : 'normal')
                +'.labelLine.show'
            );
        },

        /**
         * @param {Array.<Object>} sList 单系列图形集合
         */
        _autoLabelLayout : function (sList, center, r) {
            var leftList = [];
            var rightList = [];

            for (var i = 0, l = sList.length; i < l; i++) {
                if (sList[i]._labelPosition === 'outer' || sList[i]._labelPosition === 'outside') {
                    sList[i]._rect._y = sList[i]._rect.y;
                    if (sList[i]._rect.x < center[0]) {
                        leftList.push(sList[i]);
                    }
                    else {
                        rightList.push(sList[i]);
                    }
                }
            }
            this._layoutCalculate(leftList, center, r, -1);
            this._layoutCalculate(rightList, center, r, 1);
        },

        /**
         * @param {Array.<Object>} tList 单系列文本图形集合
         * @param {number} direction 水平方向参数，left为-1，right为1
         */
        _layoutCalculate : function(tList, center, r, direction) {
            tList.sort(function(a, b){
                return a._rect.y - b._rect.y;
            });

            // 压
            function _changeDown(start, end, delta, direction) {
                for (var j = start; j < end; j++) {
                    tList[j]._rect.y += delta;
                    tList[j].style.y += delta;
                    if (tList[j]._labelLine) {
                        tList[j]._labelLine.style.pointList[1][1] += delta;
                        tList[j]._labelLine.style.pointList[2][1] += delta;
                    }
                    if (j > start
                        && j + 1 < end
                        && tList[j + 1]._rect.y > tList[j]._rect.y + tList[j]._rect.height
                    ) {
                        _changeUp(j, delta / 2);
                        return;
                    }
                }

                _changeUp(end - 1, delta / 2);
            }

            // 弹
            function _changeUp(end, delta) {
                for (var j = end; j >= 0; j--) {
                    tList[j]._rect.y -= delta;
                    tList[j].style.y -= delta;
                    if (tList[j]._labelLine) {
                        tList[j]._labelLine.style.pointList[1][1] -= delta;
                        tList[j]._labelLine.style.pointList[2][1] -= delta;
                    }
                    if (j > 0
                        && tList[j]._rect.y > tList[j - 1]._rect.y + tList[j - 1]._rect.height
                    ) {
                        break;
                    }
                }
            }

            function _changeX(sList, isDownList, center, r, direction) {
                var x = center[0];
                var y = center[1];
                var deltaX;
                var deltaY;
                var length;
                var lastDeltaX = direction > 0
                    ? isDownList                // 右侧
                        ? Number.MAX_VALUE      // 下
                        : 0                     // 上
                    : isDownList                // 左侧
                        ? Number.MAX_VALUE      // 下
                        : 0;                    // 上

                for (var i = 0, l = sList.length; i < l; i++) {
                    deltaY = Math.abs(sList[i]._rect.y - y);
                    length = sList[i]._radius - r;
                    deltaX = (deltaY < r + length)
                        ? Math.sqrt(
                              (r + length + 20) * (r + length + 20)
                              - Math.pow(sList[i]._rect.y - y, 2)
                          )
                        : Math.abs(
                              sList[i]._rect.x + (direction > 0 ? 0 : sList[i]._rect.width) - x
                          );
                    if (isDownList && deltaX >= lastDeltaX) {
                        // 右下，左下
                        deltaX = lastDeltaX - 10;
                    }
                    if (!isDownList && deltaX <= lastDeltaX) {
                        // 右上，左上
                        deltaX = lastDeltaX + 10;
                    }

                    sList[i]._rect.x = sList[i].style.x = x + deltaX * direction;
                    if (sList[i]._labelLine) {
                        sList[i]._labelLine.style.pointList[2][0] = x + (deltaX - 5) * direction;
                        sList[i]._labelLine.style.pointList[1][0] = x + (deltaX - 20) *direction;
                    }
                    lastDeltaX = deltaX;
                }
            }

            var lastY = 0;
            var delta;
            var len = tList.length;
            var upList = [];
            var downList = [];
            for (var i = 0; i < len; i++) {
                delta = tList[i]._rect.y - lastY;
                if (delta < 0) {
                    _changeDown(i, len, -delta, direction);
                }
                lastY = tList[i]._rect.y + tList[i]._rect.height;
            }
            if (this.zr.getHeight() - lastY < 0) {
                _changeUp(len - 1, lastY - this.zr.getHeight());
            }
            for (var i = 0; i < len; i++) {
                if (tList[i]._rect.y >= center[1]) {
                    downList.push(tList[i]);
                }
                else {
                    upList.push(tList[i]);
                }
            }
            _changeX(downList, true, center, r, direction);
            _changeX(upList, false, center, r, direction);
        },

        /**
         * 参数修正&默认值赋值，重载基类方法
         * @param {Object} opt 参数
         */
        reformOption: function (opt) {
            // 常用方法快捷方式
            var _merge = zrUtil.merge;
            opt = _merge(
                      _merge(
                          opt || {}, zrUtil.clone(this.ecTheme.pie || {})
                      ),
                      zrUtil.clone(ecConfig.pie)
                  );

            // 通用字体设置
            opt.itemStyle.normal.label.textStyle = this.getTextStyle(
                opt.itemStyle.normal.label.textStyle
            );
            opt.itemStyle.emphasis.label.textStyle = this.getTextStyle(
                opt.itemStyle.emphasis.label.textStyle
            );
            this.z = opt.z;
            this.zlevel = opt.zlevel;
            return opt;
        },

        /**
         * 刷新
         */
        refresh: function (newOption) {
            if (newOption) {
                this.option = newOption;
                this.series = newOption.series;
            }

            this.backupShapeList();
            this._buildShape();
        },

        /**
         * 动态数据增加动画
         */
        addDataAnimation: function (params, done) {
            var series = this.series;
            var aniMap = {}; // seriesIndex索引参数
            for (var i = 0, l = params.length; i < l; i++) {
                aniMap[params[i][0]] = params[i];
            }

            var aniCount = 0;
            function animationDone() {
                aniCount--;
                if (aniCount === 0) {
                    done && done();
                }
            }

            // 构建新的饼图匹配差异做动画
            var sectorMap = {};
            var textMap = {};
            var lineMap = {};
            var backupShapeList = this.shapeList;
            this.shapeList = [];

            var seriesIndex;
            var isHead;
            var dataGrow;
            var deltaIdxMap = {};   // 修正新增数据后会对dataIndex产生错位匹配
            for (var i = 0, l = params.length; i < l; i++) {
                seriesIndex = params[i][0];
                isHead = params[i][2];
                dataGrow = params[i][3];
                if (series[seriesIndex]
                    && series[seriesIndex].type === ecConfig.CHART_TYPE_PIE
                ) {
                    if (isHead) {
                        if (!dataGrow) {
                            sectorMap[
                                seriesIndex
                                + '_'
                                + series[seriesIndex].data.length
                            ] = 'delete';
                        }
                        deltaIdxMap[seriesIndex] = 1;
                    }
                    else {
                        if (!dataGrow) {
                            sectorMap[seriesIndex + '_-1'] = 'delete';
                            deltaIdxMap[seriesIndex] = -1;
                        }
                        else {
                            deltaIdxMap[seriesIndex] = 0;
                        }
                    }
                    this._buildSinglePie(seriesIndex);
                }
            }
            var dataIndex;
            var key;
            for (var i = 0, l = this.shapeList.length; i < l; i++) {
                seriesIndex = this.shapeList[i]._seriesIndex;
                dataIndex = this.shapeList[i]._dataIndex;
                key = seriesIndex + '_' + dataIndex;
                // map映射让n*n变n
                switch (this.shapeList[i].type) {
                    case 'sector' :
                        sectorMap[key] = this.shapeList[i];
                        break;
                    case 'text' :
                        textMap[key] = this.shapeList[i];
                        break;
                    case 'polyline' :
                        lineMap[key] = this.shapeList[i];
                        break;
                }
            }
            this.shapeList = [];
            var targeSector;
            for (var i = 0, l = backupShapeList.length; i < l; i++) {
                seriesIndex = backupShapeList[i]._seriesIndex;
                if (aniMap[seriesIndex]) {
                    dataIndex = backupShapeList[i]._dataIndex
                                + deltaIdxMap[seriesIndex];
                    key = seriesIndex + '_' + dataIndex;
                    targeSector = sectorMap[key];
                    if (!targeSector) {
                        continue;
                    }
                    if (backupShapeList[i].type === 'sector') {
                        if (targeSector != 'delete') {
                            aniCount++;
                            // 原有扇形
                            this.zr.animate(backupShapeList[i].id, 'style')
                                .when(
                                    400,
                                    {
                                        startAngle: targeSector.style.startAngle,
                                        endAngle: targeSector.style.endAngle
                                    }
                                )
                                .done(animationDone)
                                .start();
                        }
                        else {
                            aniCount++;
                            // 删除的扇形
                            this.zr.animate(backupShapeList[i].id, 'style')
                                .when(
                                    400,
                                    deltaIdxMap[seriesIndex] < 0
                                    ? { startAngle: backupShapeList[i].style.startAngle }
                                    : { endAngle: backupShapeList[i].style.endAngle }
                                )
                                .done(animationDone)
                                .start();
                        }
                    }
                    else if (backupShapeList[i].type === 'text'
                             || backupShapeList[i].type === 'polyline'
                    ) {
                        if (targeSector === 'delete') {
                            // 删除逻辑一样
                            this.zr.delShape(backupShapeList[i].id);
                        }
                        else {
                            // 懒得新建变量了，借用一下
                            switch (backupShapeList[i].type) {
                                case 'text':
                                    aniCount++;
                                    targeSector = textMap[key];
                                    this.zr.animate(backupShapeList[i].id, 'style')
                                        .when(
                                            400,
                                            {
                                                x :targeSector.style.x,
                                                y :targeSector.style.y
                                            }
                                        )
                                        .done(animationDone)
                                        .start();
                                    break;
                                case 'polyline':
                                    aniCount++;
                                    targeSector = lineMap[key];
                                    this.zr.animate(backupShapeList[i].id, 'style')
                                        .when(
                                            400,
                                            {
                                                pointList:targeSector.style.pointList
                                            }
                                        )
                                        .done(animationDone)
                                        .start();
                                    break;
                            }

                        }
                    }
                }
            }
            this.shapeList = backupShapeList;

            // 没有动画
            if (!aniCount) {
                done && done();
            }
        },

        onclick: function (param) {
            var series = this.series;
            if (!this.isClick || !param.target) {
                // 没有在当前实例上发生点击直接返回
                return;
            }
            this.isClick = false;
            var offset;             // 偏移
            var target = param.target;
            var style = target.style;
            var seriesIndex = ecData.get(target, 'seriesIndex');
            var dataIndex = ecData.get(target, 'dataIndex');

            for (var i = 0, len = this.shapeList.length; i < len; i++) {
                if (this.shapeList[i].id === target.id) {
                    seriesIndex = ecData.get(target, 'seriesIndex');
                    dataIndex = ecData.get(target, 'dataIndex');
                    // 当前点击的
                    if (!style._hasSelected) {
                        var midAngle =
                            ((style.startAngle + style.endAngle) / 2)
                            .toFixed(2) - 0;
                        target.style._hasSelected = true;
                        this._selected[seriesIndex][dataIndex] = true;
                        target.style._x = target.style.x;
                        target.style._y = target.style.y;
                        offset = this.query(
                            series[seriesIndex],
                            'selectedOffset'
                        );
                        target.style.x += zrMath.cos(midAngle, true)
                                          * offset;
                        target.style.y -= zrMath.sin(midAngle, true)
                                          * offset;
                    }
                    else {
                        // 复位
                        target.style.x = target.style._x;
                        target.style.y = target.style._y;
                        target.style._hasSelected = false;
                        this._selected[seriesIndex][dataIndex] = false;
                    }

                    this.zr.modShape(target.id);
                }
                else if (this.shapeList[i].style._hasSelected
                         && this._selectedMode === 'single'
                ) {
                    seriesIndex = ecData.get(this.shapeList[i], 'seriesIndex');
                    dataIndex = ecData.get(this.shapeList[i], 'dataIndex');
                    // 单选模式下需要取消其他已经选中的
                    this.shapeList[i].style.x = this.shapeList[i].style._x;
                    this.shapeList[i].style.y = this.shapeList[i].style._y;
                    this.shapeList[i].style._hasSelected = false;
                    this._selected[seriesIndex][dataIndex] = false;
                    this.zr.modShape(this.shapeList[i].id);
                }
            }

            this.messageCenter.dispatch(
                ecConfig.EVENT.PIE_SELECTED,
                param.event,
                {
                    selected: this._selected,
                    target:  ecData.get(target, 'name')
                },
                this.myChart
            );
            this.zr.refreshNextFrame();
        }
    };

    zrUtil.inherits(Pie, ChartBase);

    // 图表注册
    require('../chart').define('pie', Pie);

    return Pie;
});
