/**
 * echarts图表类：树图
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Loutongbing (娄同兵, loutongbing@126.com)
 */

define(function (require) {
    var ChartBase = require('./base');
    var GOLDEN_SECTION = 0.618;
    // 图形依赖
    var IconShape = require('../util/shape/Icon');
    var ImageShape = require('zrender/shape/Image');
    var LineShape = require('zrender/shape/Line');
    var BezierCurveShape = require('zrender/shape/BezierCurve');
    // 布局依赖
    var TreeLayout = require('../layout/Tree');
    // 数据依赖
    var TreeData = require('../data/Tree');

    var ecConfig = require('../config');
    // 默认参数
    ecConfig.tree = {
        zlevel: 1,                  // 一级层叠
        z: 2,                       // 二级层叠
        calculable: false,
        clickable: true,
        rootLocation: {},
        orient: 'vertical',
        symbol: 'circle',
        symbolSize: 20,
        nodePadding: 30,
        layerPadding: 100,
        /*rootLocation: {
            x: 'center' | 'left' | 'right' | 'x%' | {number},
            y: 'center' | 'top' | 'bottom' | 'y%' | {number}
        },*/
        itemStyle: {
            normal: {
                // color: 各异,
                label: {
                    show: true
                },
                lineStyle: {
                    width: 1,
                    color: '#777',
                    type: 'curve' // curve
                }
            },
            emphasis: {

            }
        }
    };

    var ecData = require('../util/ecData');
    var zrConfig = require('zrender/config');
    var zrEvent = require('zrender/tool/event');
    var zrUtil = require('zrender/tool/util');

    /**
     * 构造函数
     * @param {Object} messageCenter echart消息中心
     * @param {ZRender} zr zrender实例
     * @param {Object} series 数据
     * @param {Object} component 组件
     * @constructor
     * @exports Tree
     */
    function Tree(ecTheme, messageCenter, zr, option, myChart) {
        // 图表基类
        ChartBase.call(this, ecTheme, messageCenter, zr, option, myChart);
        this.refresh(option);
    }
    Tree.prototype = {
        type : ecConfig.CHART_TYPE_TREE,
        /**
         * 构建单个
         *
         * @param {Object} data 数据
         */
        _buildShape : function (series, seriesIndex) {
            var data = series.data[0];
            this.tree = TreeData.fromOptionData(data.name, data.children);
            // 添加root的data
            this.tree.root.data = data;
            // 根据root坐标 方向 对每个节点的坐标进行映射
            this._setTreeShape(series);
            // 递归画出树节点与连接线
            this.tree.traverse(
                function (treeNode) {
                    this._buildItem(
                        treeNode,
                        series,
                        seriesIndex
                    );
                    // 画连接线
                    if (treeNode.children.length > 0) {
                        this._buildLink(
                            treeNode,
                            series
                        );
                    }
                },
                this
            );
            var panable = series.roam === true || series.roam === 'move';
            var zoomable = series.roam === true || series.roam === 'scale';
            // Enable pan and zooom
            this.zr.modLayer(this.getZlevelBase(), {
                panable: panable,
                zoomable: zoomable
            });
            if (
                this.query('markPoint.effect.show')
                || this.query('markLine.effect.show')
            ) {
                this.zr.modLayer(ecConfig.EFFECT_ZLEVEL, {
                    panable: panable,
                    zoomable: zoomable
                });
            }
            this.addShapeList();
        },

        /**
         * 构建单个item
         */
        _buildItem : function (
            treeNode,
            serie,
            seriesIndex
        ) {
            var queryTarget = [treeNode.data, serie];
            var symbol = this.deepQuery(queryTarget, 'symbol');
            // 多级控制
            var normal = this.deepMerge(
                queryTarget,
                'itemStyle.normal'
            ) || {};
            var emphasis = this.deepMerge(
                queryTarget,
                'itemStyle.emphasis'
            ) || {};
            var normalColor = normal.color || this.zr.getColor();
            var emphasisColor = emphasis.color || this.zr.getColor();
            var angle = -treeNode.layout.angle || 0;
            // 根节点不旋转
            if (treeNode.id === this.tree.root.id) {
                angle = 0;
            }
            var textPosition = 'right';
            if (Math.abs(angle) >= Math.PI / 2 && Math.abs(angle) < Math.PI * 3 / 2) {
                angle += Math.PI;
                textPosition = 'left';
            }
            var rotation = [
                angle,
                treeNode.layout.position[0],
                treeNode.layout.position[1]
            ];
            var shape = new IconShape({
                zlevel: this.getZlevelBase(),
                z: this.getZBase() + 1,
                rotation: rotation,
                clickable: this.deepQuery(queryTarget, 'clickable'),
                style: {
                    x: treeNode.layout.position[0] - treeNode.layout.width * 0.5,
                    y: treeNode.layout.position[1] - treeNode.layout.height * 0.5,
                    width: treeNode.layout.width,
                    height: treeNode.layout.height,
                    iconType: symbol,
                    color: normalColor,
                    brushType: 'both',
                    lineWidth: normal.borderWidth,
                    strokeColor: normal.borderColor
                },
                highlightStyle: {
                    color: emphasisColor,
                    lineWidth: emphasis.borderWidth,
                    strokeColor: emphasis.borderColor
                }
            });
            if (shape.style.iconType.match('image')) {
                shape.style.image = shape.style.iconType.replace(
                    new RegExp('^image:\\/\\/'), ''
                );
                shape = new ImageShape({
                    rotation: rotation,
                    style: shape.style,
                    highlightStyle: shape.highlightStyle,
                    clickable: shape.clickable,
                    zlevel: this.getZlevelBase(),
                    z: this.getZBase()
                });
            }
            // 节点标签样式
            if (this.deepQuery(queryTarget, 'itemStyle.normal.label.show')) {
                shape.style.text = treeNode.data.label == null ? treeNode.id : treeNode.data.label;
                shape.style.textPosition = this.deepQuery(
                    queryTarget, 'itemStyle.normal.label.position'
                );
                // 极坐标另外计算 时钟哪个侧面
                if (serie.orient === 'radial' && shape.style.textPosition !== 'inside') {
                    shape.style.textPosition = textPosition;
                }
                shape.style.textColor = this.deepQuery(
                    queryTarget, 'itemStyle.normal.label.textStyle.color'
                );
                shape.style.textFont = this.getFont(this.deepQuery(
                    queryTarget, 'itemStyle.normal.label.textStyle'
                ) || {});
            }

            if (this.deepQuery(queryTarget, 'itemStyle.emphasis.label.show')) {
                shape.highlightStyle.textPosition = this.deepQuery(
                    queryTarget, 'itemStyle.emphasis.label.position'
                );
                shape.highlightStyle.textColor = this.deepQuery(
                    queryTarget, 'itemStyle.emphasis.label.textStyle.color'
                );
                shape.highlightStyle.textFont = this.getFont(this.deepQuery(
                    queryTarget, 'itemStyle.emphasis.label.textStyle'
                ) || {});
            }
            // todo
            ecData.pack(
                shape,
                serie, seriesIndex,
                treeNode.data, 0,
                treeNode.id
            );
            this.shapeList.push(shape);
        },

        _buildLink : function (
            parentNode,
            serie
        ) {
            var lineStyle = serie.itemStyle.normal.lineStyle;
            // 折线另外计算
            if (lineStyle.type === 'broken') {
                this._buildBrokenLine(
                    parentNode,
                    lineStyle,
                    serie
                );
                return;
            }
            for (var i = 0; i < parentNode.children.length; i++) {
                var xStart = parentNode.layout.position[0];
                var yStart = parentNode.layout.position[1];
                var xEnd = parentNode.children[i].layout.position[0];
                var yEnd = parentNode.children[i].layout.position[1];
                switch (lineStyle.type) {
                    case 'curve':
                        this._buildBezierCurve(
                            parentNode,
                            parentNode.children[i],
                            lineStyle,
                            serie
                        );
                        break;
                    // 折线
                    case 'broken':
                        break;
                    // default画直线
                    default:
                        var shape = this._getLine(
                            xStart,
                            yStart,
                            xEnd,
                            yEnd,
                            lineStyle
                        );
                        this.shapeList.push(shape);
                }
            }
        },
        _buildBrokenLine: function (
            parentNode,
            lineStyle,
            serie
        ) {
            // 引用_getLine需要把type改为solid
            var solidLineStyle = zrUtil.clone(lineStyle);
            solidLineStyle.type = 'solid';
            var shapes = [];
            var xStart = parentNode.layout.position[0];
            var yStart = parentNode.layout.position[1];
            var orient = serie.orient;

            // 子节点的y
            var yEnd = parentNode.children[0].layout.position[1];
            // 中点x y
            var xMiddle = xStart;
            var yMiddle = yStart + (yEnd - yStart) * (1 - GOLDEN_SECTION);
            // 中线的起始
            var xMiddleStart = parentNode.children[0].layout.position[0];
            var yMiddleStart = yMiddle;
            var xMiddleEnd = parentNode.children[parentNode.children.length - 1].layout.position[0];
            var yMiddleEnd = yMiddle;
            // 水平状态
            if (orient === 'horizontal') {
                var xEnd = parentNode.children[0].layout.position[0];
                xMiddle = xStart + (xEnd - xStart) * (1 - GOLDEN_SECTION);
                yMiddle = yStart;
                xMiddleStart = xMiddle;
                yMiddleStart = parentNode.children[0].layout.position[1];
                xMiddleEnd = xMiddle;
                yMiddleEnd = parentNode.children[parentNode.children.length - 1].layout.position[1];
            }
            // 第一条 从根节点垂直向下
            shapes.push(
                this._getLine(
                    xStart,
                    yStart,
                    xMiddle,
                    yMiddle,
                    solidLineStyle
                )
            );
            // 第二条 横向
            shapes.push(
                this._getLine(
                    xMiddleStart,
                    yMiddleStart,
                    xMiddleEnd,
                    yMiddleEnd,
                    solidLineStyle
                )
            );
            // 第三条 垂直向下到子节点
            for (var i = 0; i < parentNode.children.length; i++) {
                xEnd = parentNode.children[i].layout.position[0];
                yEnd = parentNode.children[i].layout.position[1];
                // 水平状态
                if (orient === 'horizontal') {
                    yMiddleStart = yEnd;
                }
                else {
                    xMiddleStart = xEnd;
                }
                shapes.push(
                    this._getLine(
                        xMiddleStart,
                        yMiddleStart,
                        xEnd,
                        yEnd,
                        solidLineStyle
                    )
                );
            }
            this.shapeList = this.shapeList.concat(shapes);
        },
        _getLine: function (
            xStart,
            yStart,
            xEnd,
            yEnd,
            lineStyle
        ) {
            if (xStart === xEnd) {
                xStart = xEnd = this.subPixelOptimize(xStart, lineStyle.width);
            }
            if (yStart === yEnd) {
                yStart = yEnd = this.subPixelOptimize(yStart, lineStyle.width);
            }
            return new LineShape({
                zlevel: this.getZlevelBase(),
                hoverable: false,
                style: zrUtil.merge(
                    {
                        xStart: xStart,
                        yStart: yStart,
                        xEnd: xEnd,
                        yEnd: yEnd,
                        lineType: lineStyle.type,
                        strokeColor: lineStyle.color,
                        lineWidth: lineStyle.width
                    },
                    lineStyle,
                    true
                )
            });
        },
        _buildBezierCurve: function (
            parentNode,
            treeNode,
            lineStyle,
            serie
        ) {
            var offsetRatio = GOLDEN_SECTION;
            var orient = serie.orient;
            var xStart = parentNode.layout.position[0];
            var yStart = parentNode.layout.position[1];
            var xEnd = treeNode.layout.position[0];
            var yEnd = treeNode.layout.position[1];
            var cpX1 = xStart;
            var cpY1 = (yEnd - yStart) * offsetRatio + yStart;
            var cpX2 = xEnd;
            var cpY2 = (yEnd - yStart) * (1 - offsetRatio) + yStart;
            if (orient === 'horizontal') {
                cpX1 = (xEnd - xStart) * offsetRatio + xStart;
                cpY1 = yStart;
                cpX2 = (xEnd - xStart) * (1 - offsetRatio) + xStart;
                cpY2 = yEnd;
            }
            else if (orient === 'radial') {
                // 根节点 画直线
                if (parentNode.id === this.tree.root.id) {
                    cpX1 = (xEnd - xStart) * offsetRatio + xStart;
                    cpY1 = (yEnd - yStart) * offsetRatio + yStart;
                    cpX2 = (xEnd - xStart) * (1 - offsetRatio) + xStart;
                    cpY2 = (yEnd - yStart) * (1 - offsetRatio) + yStart;
                }
                else {
                    var xStartOrigin = parentNode.layout.originPosition[0];
                    var yStartOrigin = parentNode.layout.originPosition[1];
                    var xEndOrigin = treeNode.layout.originPosition[0];
                    var yEndOrigin = treeNode.layout.originPosition[1];
                    var rootX = this.tree.root.layout.position[0];
                    var rootY = this.tree.root.layout.position[1];

                    cpX1 = xStartOrigin;
                    cpY1 = (yEndOrigin - yStartOrigin) * offsetRatio + yStartOrigin;
                    cpX2 = xEndOrigin;
                    cpY2 = (yEndOrigin - yStartOrigin) * (1 - offsetRatio) + yStartOrigin;
                    var rad = (cpX1 - this.minX) / this.width * Math.PI * 2;
                    cpX1 = cpY1 * Math.cos(rad) + rootX;
                    cpY1 = cpY1 * Math.sin(rad) + rootY;

                    rad = (cpX2 - this.minX) / this.width * Math.PI * 2;
                    cpX2 = cpY2 * Math.cos(rad) + rootX;
                    cpY2 = cpY2 * Math.sin(rad) + rootY;
                }
            }
            var shape = new BezierCurveShape({
                zlevel: this.getZlevelBase(),
                hoverable: false,
                style: zrUtil.merge(
                    {
                        xStart: xStart,
                        yStart: yStart,
                        cpX1: cpX1,
                        cpY1: cpY1,
                        cpX2: cpX2,
                        cpY2: cpY2,
                        xEnd: xEnd,
                        yEnd: yEnd,
                        strokeColor: lineStyle.color,
                        lineWidth: lineStyle.width
                    },
                    lineStyle,
                    true
                )
            });
            this.shapeList.push(shape);
        },
        _setTreeShape : function (serie) {
            // 跑出来树的layout
            var treeLayout = new TreeLayout(
                {
                    nodePadding: serie.nodePadding,
                    layerPadding: serie.layerPadding
                }
            );
            this.tree.traverse(
                function (treeNode) {
                    var queryTarget = [treeNode.data, serie];
                    var symbolSize = this.deepQuery(queryTarget, 'symbolSize');
                    if (typeof symbolSize === 'number') {
                        symbolSize = [symbolSize, symbolSize];
                    }
                    treeNode.layout = {
                        width: symbolSize[0], // 节点大小
                        height: symbolSize[1]
                    };
                },
                this
            );
            treeLayout.run(this.tree);
            // 树的方向
            var orient = serie.orient;
            var rootX = serie.rootLocation.x;
            var rootY = serie.rootLocation.y;
            var zrWidth = this.zr.getWidth();
            var zrHeight = this.zr.getHeight();
            if (rootX === 'center') {
                rootX = zrWidth * 0.5;
            }
            else {
                rootX = this.parsePercent(rootX, zrWidth);
            }
            if (rootY === 'center') {
                rootY = zrHeight * 0.5;
            }
            else {
                rootY = this.parsePercent(rootY, zrHeight);
            }
            rootY = this.parsePercent(rootY, zrHeight);
            // 水平树
            if (orient === 'horizontal') {
                rootX = isNaN(rootX) ? 10 : rootX;
                rootY = isNaN(rootY) ? zrHeight * 0.5 : rootY;
            }
            // 极坐标
            if (orient === 'radial') {
                rootX = isNaN(rootX) ? zrWidth * 0.5 : rootX;
                rootY = isNaN(rootY) ? zrHeight * 0.5 : rootY;
            }
            // 纵向树
            else {
                rootX = isNaN(rootX) ? zrWidth * 0.5 : rootX;
                rootY = isNaN(rootY) ? 10 : rootY;
            }
            // tree layout自动算出来的root的坐标
            var originRootX = this.tree.root.layout.position[0];
            // 若是极坐标,则求最大最小值
            if (orient === 'radial') {
                var minX = Infinity;
                var maxX = 0;
                var maxWidth = 0;
                this.tree.traverse(
                    function (treeNode) {
                        maxX = Math.max(maxX, treeNode.layout.position[0]);
                        minX = Math.min(minX, treeNode.layout.position[0]);
                        maxWidth = Math.max(maxWidth, treeNode.layout.width);
                    }
                );
                //  2 * maxWidth 还不大好但至少保证绝不会重叠 todo
                this.width = maxX - minX + 2 * maxWidth;
                this.minX = minX;
            }
            this.tree.traverse(
                function (treeNode) {
                    var x;
                    var y;
                    if (orient === 'vertical' && serie.direction === 'inverse') {
                        x = treeNode.layout.position[0] - originRootX + rootX;
                        y = rootY - treeNode.layout.position[1];
                    }
                    else if (orient === 'vertical') {
                        x = treeNode.layout.position[0] - originRootX + rootX;
                        y = treeNode.layout.position[1] + rootY;
                    }
                    else if (orient === 'horizontal' && serie.direction === 'inverse') {
                        y = treeNode.layout.position[0] - originRootX + rootY;
                        x = rootX - treeNode.layout.position[1];
                    }
                    else if (orient === 'horizontal') {
                        y = treeNode.layout.position[0] - originRootX + rootY;
                        x = treeNode.layout.position[1] + rootX;
                    }
                    // 极坐标
                    else {
                        x = treeNode.layout.position[0];
                        y = treeNode.layout.position[1];
                        // 记录原始坐标，以后计算贝塞尔曲线的控制点
                        treeNode.layout.originPosition = [x, y];
                        var r = y;
                        var angle = (x - minX) / this.width * Math.PI * 2;
                        x = r * Math.cos(angle) + rootX;
                        y = r * Math.sin(angle) + rootY;
                        treeNode.layout.angle = angle;
                    }
                    treeNode.layout.position[0] = x;
                    treeNode.layout.position[1] = y;
                },
                this
            );
        },
        /*
         * 刷新
         */
/*        refresh: function (newOption) {
            this.clear();
            if (newOption) {
                this.option = newOption;
                this.series = newOption.series;
            }

            this._buildShape();
        }*/
        refresh: function (newOption) {
            this.clear();

            if (newOption) {
                this.option = newOption;
                this.series = this.option.series;
            }

            // Map storing all trees of series

            var series = this.series;
            var legend = this.component.legend;

            for (var i = 0; i < series.length; i++) {
                if (series[i].type === ecConfig.CHART_TYPE_TREE) {
                    series[i] = this.reformOption(series[i]);

                    var seriesName = series[i].name || '';
                    this.selectedMap[seriesName] = 
                        legend ? legend.isSelected(seriesName) : true;
                    if (!this.selectedMap[seriesName]) {
                        continue;
                    }

                    this._buildSeries(series[i], i);
                }
            }
        },

        _buildSeries: function (series, seriesIndex) {
            /*var tree = Tree.fromOptionData('root', series.data);

            this._treesMap[seriesIndex] = tree;*/

            // this._buildTreemap(tree.root, seriesIndex);
            this._buildShape(series, seriesIndex);
        }
    };

    zrUtil.inherits(Tree, ChartBase);

    // 图表注册
    require('../chart').define('tree', Tree);

    return Tree;
});
