/**
 * 首页监控图相关功能
 *
 * @since 2022-01-01
 * @author pengys
 */
(function(factory) {
    if(typeof define === 'function' && define.amd) {
        var scripts = ['jquery','bootstrap','gritter'];
        define(scripts, factory);
    }else {
        factory(jQuery);
    }
}(function($) {
    var d3,modal;
    function operatorError () {
        horizon.notice.error(horizon.lang.message['operateError']);
    };
    var containerSize = {
        height: function() {
            return horizon.tools.getPageContentHeight();
        },
        width: function() {
            return $('.page-content-area').outerWidth(true);
        },
    };
    var flowMonitor = {
        init: function() {
            if ($('.horizon-task-modal').length >=2 ){
                $('.page-content-area').find('.horizon-task-modal').remove();
                if (horizon.modal){
                    modal = horizon.modal;
                }else {
                    horizon.engine.iframe.init();
                    modal =  horizon.engine.iframe;
                }
            }else {
                horizon.engine.iframe.init();
                modal =  horizon.engine.iframe;
            }
            //初始化流程监控图
            $('#product_tree').css({
                'width': '100%',
                'height': containerSize.height()
            });
            var browser = horizon.tools.browser();
            if(browser.browser == 'IE' && browser.version <= 8.0) {
                window.attachEvent('onresize', function() {
                    flowMonitor.resize();
                });
            }else{
                window.addEventListener('resize', function() {
                    flowMonitor.resize();
                });
            }
            $('.sidebar-collapse').on(horizon.tools.clickEvent() + '.ace.menu', function(e){
                setTimeout(function(){
                },100);
            });
            flowMonitor.ajaxFlowMonitorData();
        },
        resize: function() {
            if($('body').hasClass('embed') && $(window).width() < 768) {
                $('.hid-left').removeClass('hidden');
                $('.hid-right').addClass('hidden');
            }else if($('body').hasClass('embed') && $(window).width() >= 768){
                $('.hid-right').removeClass('hidden');
                $('.hid-left').addClass('hidden');
            }
        },
        ajaxFlowMonitorData: function() {
            $.ajax({
                url: horizon.tools.formatUrl('/area/dept/instance/tree'),
                dataType: 'json',
                cache: false,
                data:{
                    width:containerSize.width(),
                    nodeSpace: 250,
                    rectLength: 200
                },
                error: function() {
                    operatorError();
                },
                success: function(data) {
                    var refresh = flowMonitor.ajaxFlowAreaRefresh();
                    drawing( {
                        "data":data,
                        "refresh":refresh
                    } );
                }
            });
        },
        ajaxFlowAreaRefresh: function() {
            var refresh = null;
            $.ajax({
                url: horizon.tools.formatUrl('/area/dept/flow/refresh'),
                dataType: 'json',
                cache: false,
                async:false,
                error: function() {
                    operatorError();
                },
                success: function(data) {
                    if(data) {
                        refresh = data
                    }
                }
            });
            return refresh;
        }
    }
    var	drawing = function(option) {
        var rectHeight = 50; //节点rect的高度
        //var maxRectWidth = 200; //节点rect的最大宽度
        //var minRectWidth = 80; //节点rect的最小
        var rectWidth = 200;
        var rootRectHeight = 80; //根节点rect的宽度
        var forUpward = true

        var treeChart = function(d3Object) {
            this.d3 = d3Object;
            this.directions = 'downward';
        };
        treeChart.prototype.drawChart = function() {
            // First get tree data for both directions.
            this.treeData = {};
            var self = this;
            self.treeData['downward'] = option['data'];
            self.treeData['refresh'] = option['refresh'];
            self.graphTree(self.getTreeConfig());
        };

        treeChart.prototype.getTreeConfig = function() {
            var treeConfig = {
                'margin': {
                    'top': 0,
                    'right': 0,
                    'bottom': 0,
                    'left': 0
                }
            }
            treeConfig.chartWidth = (containerSize.width() - treeConfig.margin.right - treeConfig.margin.left);
            treeConfig.chartHeight = (containerSize.height() - treeConfig.margin.top - treeConfig.margin.bottom);
            treeConfig.centralHeight = treeConfig.chartHeight / 2;
            treeConfig.centralWidth = treeConfig.chartWidth / 2;
            treeConfig.linkLength = 150;
            treeConfig.duration = 500; //动画时间
            return treeConfig;
        };

        treeChart.prototype.graphTree = function(config) {
            var previousEvent;
            var selectNode = null;
            var self = this;
            var d3 = this.d3;
            var refresh = self.treeData['refresh'];
            var direction = this.directions;
            var data = self.treeData[direction];
            data.x0 = config.centralWidth;
            data.y0 = config.centralHeight;

            //data.children.forEach(collapse);
            var linkLength = config.linkLength;
            var duration = config.duration;
            var colorClass = {
                "overexceed": "tooltip-color-darkred",
                "exceed": "tooltip-color-red",
                "warn": "tooltip-color-orange",
                "approve": "tooltip-color-green",
            }
            var sideWidth = 0;
            if ($(".horizon-sidebar:not(hidden)").length > 0 ){
                sideWidth = $(".horizon-sidebar:not(hidden)").width();
            }
            var browser = horizon.tools.browser().browser;
            var wheelEvent = (browser=='firefox')?'wheel':'mousewheel';
            var colors = {
                "exceed" : "#E80F0F",
                "overexceed": "#B50101",
                "warn": "#FFD045",
                "approve": "#4FD27D"
            }
            // var nodeSpace = maxRectWidth + 50;
            var nodeSpace = rectWidth + 50;

            // var diagonal = d3.svg.diagonal().projection(function(d) {return [d.x, d.y];});
            // var diagonal = d3.svg.diagonal()
            //     .source(function(d) {
            //         return {
            //             "x": d.source.x,
            //             "y": d.source.root? (d.source.y + 20) : (d.source.y + 50)
            //         };
            //     })
            //     .target(function(d) {
            //         return {
            //             "x": d.target.x,
            //             "y": d.target.y
            //         };
            //     })
            //     .projection(function(d) {
            //         return [d.x, d.y];
            //     });
            var diagonal = function(obj) {  //折线
                //折线出发目标
                var s = obj.source;
                var sy = s.root? s.y + 55: s.y + 40
                //折线结束目标
                var t = obj.target;
                var ty = t.y
                return "M"+ s.x  +","+ sy+
                    "L" + s.x +"," +  (sy + (ty-sy)/2)+
                    "L" + t.x + "," + (sy + (ty-sy)/2) +
                    "L" + t.x  + "," + ty;
            }

            var zoom = d3.behavior.zoom().scaleExtent([0.2, 2.5]).on('zoom', redraw);

            var tooltip = d3.select('#treecontainer')
                .append('div')
                // .attr("width","auto")
                // .attr("height","auto")
                //.style("min-width",200)
                .classed('pricing-span-extend',true)
                .style('position', 'absolute')
                //.style('padding', '5px 5px')
                //.style('pointer-events','none')
                .style('visibility', 'hidden');

            var widgetBox = tooltip
                .append('div')
                .classed('widget-box',true)
                .classed ('pricing-box-small',true);
            var widgetHeader = widgetBox
                .append('div')
                .classed('tooltip-header',true);
            var widgetTitle= widgetHeader
                .append('div')
                .classed('tooltip-title',true)
                .classed('bigger',true)
                .classed('lighter',true)
            var title =  widgetTitle.append('strong');
            var widgetBody = widgetBox
                .append('div')
                .classed('widget-body',true);
            var widgetMain = widgetBody.append('div')
                .classed('widget-main',true)
                .classed('no-padding',true);
            var ulList = widgetMain
                .append('ul')
                .classed('ul-list-unstyled',true)
                .classed('pricing-table',true)
                .classed('li-state-active',true);

            var approveLi = ulList.append('li')
                .style('cursor', 'pointer')
                .classed('li-list-unstyled',true)
                .on('click',instanceListClick)
            var warnLi = ulList.append('li')
                .style('cursor', 'pointer')
                .classed('li-list-unstyled',true)
                .on('click',instanceListClick)
            var exceedLi = ulList.append('li')
                .style('cursor', 'pointer')
                .on('click',instanceListClick)
            var overexceedLi = ulList.append('li')
                .style('cursor', 'pointer')
                .classed('li-list-unstyled',true)
                .on('click',instanceListClick)

            var totalLi = ulList.append('li')
                .style('cursor', 'pointer')
                .classed('li-list-unstyled',true)
                .on('click',instanceListClick)

            d3.select('#treecontainer')
                .append('div')
                .classed('prompt',true)
                .html(
                    '<ul class="prompt-breadcrumb">'+
                    '<div class="list-show list-color-grey ">'+refresh+'&nbsp;&nbsp;'+horizon.lang.flowarea['refresh'] +'</div>'+
                    '<li class="list-show list-color-green">' + horizon.lang.flowstatus['todo'] +'</li>'+
                    '<li class="list-show list-color-orange">' + horizon.lang.flowstatus['warn'] +'</li>'+
                    '<li class="list-show list-color-red" >' + horizon.lang.flowstatus['extended'] +'</li>'+
                    '<li class="list-show list-color-darkred">' + horizon.lang.flowstatus['overexceed'] +'</li>'+
                    '</ul>'

                );
            d3.select(document).on('mouseup', clearLeftClick);
            // 是否可见（一开始设置为隐藏）
            var svg = d3.select('#product_tree')
                .append('svg')
                .attr('width', config.chartWidth + config.margin.right + config.margin.left)
                .attr('height', config.chartHeight + config.margin.top + config.margin.bottom)
                .attr('xmlns','http://www.w3.org/2000/svg')
                .on('mousedown', disableRightClick)
                .call(zoom)
                .on('dblclick.zoom', null);
            var treeG = null;
            setTimeout(function () {
                treeG = svg.append('g')
                    .attr('class', 'gbox')
                    .attr('transform', 'translate(' + config.margin.left + ',' + config.margin.top + ') scale(1)');
                update(data, data, treeG);
            },100)


            //箭头(下半部分)
            // var markerDown = svg.append("marker")
            //     .attr("id", "resolvedDown")
            //     .attr("markerUnits", "strokeWidth") //设置为strokeWidth箭头会随着线的粗细发生变化
            //     .attr("markerUnits", "userSpaceOnUse")
            //     .attr("viewBox", "0 -5 10 10") //坐标系的区域
            //     .attr("refX", 0) //箭头坐标
            //     .attr("refY", 0)
            //     .attr("markerWidth", 12) //标识的大小
            //     .attr("markerHeight", 12)
            //     .attr("orient", "90") //绘制方向，可设定为：auto（自动确认方向）和 角度值
            //     .attr("stroke-width", 2) //箭头宽度
            //     .append("path")
            //     .attr("d", "M0,-5L10,0L0,5") //箭头的路径
            //     .attr('fill', '#000'); //箭头颜色
            // Initialize the tree nodes and update chart.

            function update(source, originalData, g) {
                forUpward = direction == 'upward';
                var node_class = direction + 'Node';
                var link_class = direction + 'Link';
                var downwardSign = 1;

                var tree = d3.layout.tree().nodeSize([nodeSpace, 0]);
                var nodes = tree.nodes(originalData);
                var links = tree.links(nodes);
                var offsetX = - config.centralWidth;
                nodes.forEach(function(d) {
                    d.y = downwardSign * (d.depth * linkLength) + 20;// + config.centralHeight;
                    d.x = d.x - offsetX;
                    if(d.root) {
                        d.x = config.centralWidth;
                        d.y += downwardSign * 0; // 上下两树图根节点之间的距离
                    }
                });

                // Update the node.
                var node = g.selectAll('g.' + node_class).data(nodes, function(d) {
                    return d.id ;
                });

                var nodeEnter = node.enter().append('g')
                    .attr('class', node_class)
                    .classed('root',function (d) {
                        return d.root;
                    } )
                    .attr('id',function (d) {
                        return 'g'+d.id
                    })
                    .attr('transform', function(d) {
                        return 'translate(' + source.x0 + ',' + source.y0 + ')';
                    })
                    .style('cursor', function(d) {
                        return 'pointer';
                    })
                    //.on('click', gClick)
                    .on(wheelEvent, mouseWheel)
                    .on('mouseenter', function (d) {
                        var toolColor =  colorClass[d.status]
                        widgetBox.classed('tooltip-color-darkred',false)
                            .classed('tooltip-color-red',false)
                            .classed('tooltip-color-orange',false)
                            .classed('tooltip-color-green',false)
                            .classed(toolColor,true);
                        title.text(d.name);
                        // approveLi.html('').html('<a href="#">'+ horizon.lang.flowarea['approve'] + ':'+ d.approveNum + '</a>');
                        // warnLi.html('').html('<a>'+horizon.lang.flowarea['warn'] +':' + d.warnNum + '</a>');
                        // exceedLi.html('').html('<a>'+horizon.lang.flowarea['exceed'] +':' + d.exceedNum + '</a>');
                        // overexceedLi.html('').html('<a>'+horizon.lang.flowarea['overexceed'] +':'+ d.overexceedNum + '</a>');
                        approveLi
                            .text( horizon.lang.flowarea['approve'] + ':'+ d.approveNum)
                            .attr('deptId', d.id)
                            .attr('title', d.name)
                            .attr('status', 'normal');
                        warnLi
                            .text(horizon.lang.flowarea['warn'] +':' + d.warnNum)
                            .attr('deptId', d.id)
                            .attr('title', d.name)
                            .attr('status', 'warn');
                        exceedLi
                            .text(horizon.lang.flowarea['exceed'] +':' + d.exceedNum)
                            .attr('deptId', d.id)
                            .attr('title', d.name)
                            .attr('status', 'exceed');
                        overexceedLi
                            .text(horizon.lang.flowarea['overexceed'] +':'+ d.overexceedNum)
                            .attr('deptId', d.id)
                            .attr('title', d.name)
                            .attr('status', 'overexceed');
                        totalLi
                            .text(horizon.lang.flowarea['total'] +':'+d.totalNum)
                            .attr('title', d.name)
                            .attr('deptId', d.id);
                        var height = d3.select(this).node().getBoundingClientRect().height;
                        var x = d3.select(this).node().getBoundingClientRect().left- sideWidth;
                        var y = d3.select(this).node().getBoundingClientRect().top;
                        var top =  y > 250 ? y - height- 230: y ;
                        tooltip.style('top', top + 'px')
                            .style('left',x +'px')
                            .style('visibility', 'visible');
                        d3.event.stopImmediatePropagation();
                        d3.event.preventDefault && d3.event.preventDefault();
                        return false
                    });

                nodeEnter.append("svg:rect")
                    .attr("x", function(d) {
                        if (d.root){
                            var rootLength = d.name.length * 20;
                            return rootLength >= rectWidth ? -rootLength/2: -rectWidth/2
                        }
                        // var length = d.name.length * 15;
                        // length = length > maxRectWidth ? maxRectWidth:length;
                        // length = length < minRectWidth ? minRectWidth:length;
                        // return - length/2;
                        return -rectWidth/2
                    })
                    .attr("y", function(d) {
                        return d.root ? -20 : 0;
                    })
                    .attr("width", function(d) {
                        if (d.root){
                            var rootLength = d.name.length * 20;
                            return  rootLength >= rectWidth ? rootLength:rectWidth
                        }
                        // var length = d.name.length * 15;
                        // length = length > maxRectWidth ? maxRectWidth:length;
                        // length = length < minRectWidth ? minRectWidth:length;
                        // return length ;
                        return rectWidth
                    })
                    .attr("height", function(d) {
                        return d.root ? rootRectHeight : rectHeight;
                    })
                    .attr("rx", 10)
                    .style("stroke", function(d) {
                        return colors[d.status];
                    })
                    .style("fill",function (d) {
                        return colors[d.status]
                    })
                    .attr("id", function(d) {
                        return d.id;
                    });

                //nodeEnter.append('circle').attr('r', 1e-6);
                //拼接组织机构名字
                nodeEnter.append("text")
                    .attr("class", "linkname")
                    .attr("x", function(d) {
                        if(d.root){
                            return '0';
                        }
                        if(d.name.length > 12){
                            return -(rectWidth/2) + 15;
                        }else {
                            return - (d.name.length) * 15/2
                        }
                        // var length = d.name.length * 15;
                        // length = length > maxRectWidth ? maxRectWidth:length;
                        // length = length < minRectWidth ? minRectWidth:length;
                        // return -length/2;

                    })
                    .attr('dy', function(d) {
                        if (d.root){
                            return 25
                        }
                        if(d.name.length > 12){
                            return 20
                        }
                        return 30;
                    })
                    .attr("text-anchor", function(d) {
                        return d.root ? 'middle' : "start";
                    })
                    .attr('fill', '#000')
                    .text(function(d) {
                        if (d.root){
                            return d.name;
                        }
                        return d.name.length > 12 ? d.name.substr(0, 12): d.name
                    })
                    .style({
                        'fill-opacity': 1e-6,
                        'font-size': function(d) {
                            return d.root ? '18px' : '14px';
                        },
                        'cursor': "pointer"
                    });
                //拼接组织机构名字第二段
                nodeEnter.append("text")
                    .attr("class", "linkname")
                    .attr("x", function(d) {
                        if(d.root){
                            return '0';
                        }
                        if(d.name.length > 12){
                            return - (d.name.substr(12).length) * 15/2
                        }

                        // var length = d.name.length * 15;
                        // length = length > maxRectWidth ? maxRectWidth:length;
                        // length = length < minRectWidth ? minRectWidth:length;
                        // return -length/2;
                    })
                    .attr('dy', function(d) {
                        return  d.root? '.35em': 40
                    })
                    .attr("text-anchor", function(d) {
                        return d.root ? 'middle' : "start";
                    })
                    .attr('fill', '#000')
                    .text(function(d) {
                        return !d.root && d.name.length > 12 ? d.name.substr(12) : '';
                    })
                    .style({
                        'font-size': '14px',
                        'cursor': "pointer"
                    });

                // Transition nodes to their new position.原有节点更新到新位置
                var nodeUpdate = node.transition().duration(duration)
                    .attr('transform', function(d) {
                        return 'translate(' + d.x + ',' + d.y + ')';
                    });


                // nodeUpdate.select('circle')
                //     .attr('r',6)
                //     .attr('cy', function(d) {
                //         return d.root ? 20 : 62;
                //     })
                //     .style('fill', function(d) {
                //         return "#fff";
                //     })
                //     .style('stroke', function(d) {
                //         return "#8b4513"
                //     })
                //     .style('fill-opacity', function(d) {
                //         return 0.35;
                //     });

                //代表是否展开的+-号
                // nodeEnter.append("svg:text")
                //     .attr("class", "isExpand")
                //     .attr("x", "0")
                //     .attr("dy",function (d) {
                //        return d.root ? 20 : 65;
                //     })
                //     .attr("text-anchor", "middle")
                //     .style("fill", "#000")
                //     .text(function(d) {
                //         return d.root?'-':"+";
                //     });
                nodeUpdate.select('text').style('fill-opacity', 1)

                var nodeExit = node.exit().transition().duration(duration)
                    .attr('transform', function(d) {
                        return 'translate(' + source.x + ',' + source.y + ')';
                    }).remove();
                nodeExit.select('circle')
                    .attr('r', 1e-6)
                nodeExit.select('text')
                    .style('fill-opacity', 1e-6);

                var link = g.selectAll('path.' + link_class)
                    .data(links, function(d) {
                        return d.target.id;
                    });

                link.enter().insert('path', 'g')
                    .attr('class', link_class)
                    .attr('stroke', '#000')
                    .attr('fill',"none")
                    .attr('stroke-width','1.5px')
                    .attr('opacity', 1)
                    .attr('d', function(d) {
                        var o = {
                            x: source.x0,
                            y: source.y0
                        };
                        return diagonal({
                            source: o,
                            target: o
                        });
                    })
                    // .attr("marker-end", function(d) {
                    //     return "url(#resolvedDown)";
                    // }) //根据箭头标记的id号标记箭头;
                    .attr("id", function(d, i) {
                        return "path" + i;
                    })

                //绘制曲线
                link.transition().duration(duration).attr('d', diagonal);

                link.exit()
                    .transition()
                    .duration(duration)
                    .attr('d', function(d) {
                        var o = {
                            x: source.x,
                            y: source.y
                        };
                        return diagonal({
                            source: o,
                            target: o
                        });
                    }).remove();

                nodes.forEach(function(d) {
                    d.x0 = d.x;
                    d.y0 = d.y;
                });
                // function Change_modal () {
                //     _this.Modal = true
                // }
                function click(d) {
                    if(d.root) {
                        return;
                    }
                    if(d.children) {
                        d._children = d.children;
                        d.children = null;
                        //d3.select(this).text('+').attr("isExpand",false);
                    } else {
                        d.children = d._children;
                        d._children = null;
                        // expand all if it's the first node
                        if(d.root) {
                            d.children.forEach(expand);
                        }
                        //d3.select(this).text('-').attr("isExpand",false);
                    }
                    update(d, originalData, g);
                }
                function gClick(d) {
                    selectNode = d;
                    // d3.select(this).select('rect').style("fill", "#428bca") ;
                }

                function mouseWheel(d) {
                    if(d.root) {
                        d3.event.stopImmediatePropagation();
                        return;
                    }
                    tooltip.style('visibility', 'hidden');
                    var _this = this
                    var isExpand = d3.select(this)
                        //.select('.isExpand')
                        .attr("isExpand");
                    var x = config.centralWidth-rectWidth/2;
                    var y = 100;
                    if(d3.event.wheelDelta > 0 || d3.event.deltaY < 0) {
                        if (isExpand && isExpand == "true"){
                            d3.event.stopImmediatePropagation();
                            return;
                        }
                        if(d._children) {
                            d.children = d._children;
                            d._children = null;
                            // expand all if it's the first node
                            if(d.root) {
                                d.children.forEach(expand);
                            }
                            d3.select(this)
                                //.select('.isExpand').text('-')
                                .attr("isExpand",true);
                            update(d, originalData, g);
                            setTimeout(function () {
                                var transform = getFloat(treeG.attr('transform'));
                                var nodeX = d3.select(_this).node().getBoundingClientRect().left;
                                var nodeY = d3.select(_this).node().getBoundingClientRect().top;
                                var moveX = x - nodeX;
                                var moveY = y - nodeY;
                                var endX = parseFloat(transform[0]) + moveX;
                                var endY = parseFloat(transform[1] ? transform[1]: transform[0]) + moveY;
                                var scale = transform.length > 2? parseFloat(transform[2]) : 1;
                                treeG.transition()
                                    .duration(600).attr('transform', 'translate(' + endX +','+ endY +')' +
                                    ' scale(' + scale + ')');
                            },300);
                        }else {
                            $.ajax({
                                url: horizon.tools.formatUrl('/area/dept/instance/tree'),
                                dataType: 'json',
                                data:{
                                    parentId:d.id
                                },
                                cache: false,
                                error: function() {
                                    operatorError();
                                },
                                success: function(data) {
                                    if(data && data.length > 0) {
                                        d.children = data;
                                        d._children = null;
                                        d3.select(_this)
                                            //.select('.isExpand').text('-')
                                            .attr("isExpand",true);
                                        update(d, originalData, g);
                                        setTimeout(function () {
                                            var transform = getFloat(treeG.attr('transform'));
                                            var nodeX = d3.select(_this).node().getBoundingClientRect().left;
                                            var nodeY = d3.select(_this).node().getBoundingClientRect().top;
                                            var moveX = x - nodeX;
                                            var moveY = y - nodeY;
                                            var endX = parseFloat(transform[0]) + moveX;
                                            var endY = parseFloat(transform[1] ? transform[1]: transform[0]) + moveY;
                                            var scale = transform.length > 2? parseFloat(transform[2]) : 1;
                                            treeG.transition()
                                                .duration(600).attr('transform', 'translate(' + endX +','+ endY +')' +
                                                ' scale(' + scale + ')');
                                        },300);

                                    }
                                }
                            });
                        }
                    }else {
                        if(d.children){
                            d._children = d.children;
                            d.children = null;
                            d3.select(this)
                                //.select('.isExpand').text('+')
                                .attr("isExpand",false);
                            update(d, originalData, g);
                            setTimeout(function () {
                                var transform = getFloat(treeG.attr('transform'));
                                var cX = d3.select('#g'+ d.parentId).node().getBoundingClientRect().left ;
                                var cY = d3.select('#g'+ d.parentId).node().getBoundingClientRect().top;
                                var moveX = cX - x;
                                var moveY = cY - y;
                                var endX = parseFloat(transform[0]) - moveX;
                                var endY = parseFloat(transform[1] ? transform[1]: transform[0]) - moveY;
                                var scale = transform.length > 2? parseFloat(transform[2]) : 1;
                                treeG.transition()
                                    .duration(600).attr('transform', 'translate(' + endX +','+ endY +')' +
                                    ' scale(' + scale + ')');
                            },300);
                        }

                    }
                    d3.event.stopImmediatePropagation();
                }
            }

            function expand(d) {
                if(d._children) {
                    d.children = d._children;
                    d.children.forEach(expand);
                    d._children = null;
                }
            }

            function collapse(d) {
                if(d.children && d.children.length != 0) {
                    d._children = d.children;
                    d._children.forEach(collapse);
                    d.children = null;
                }
            }
            function redraw() {
                tooltip.style('visibility', 'hidden');
                var eventType = d3.event.sourceEvent.type;
                if (eventType == 'mousemove'){
                    var event = d3.event.sourceEvent;
                    var moveX = previousEvent ? event.screenX - previousEvent.screenX: 0;
                    var moveY = previousEvent ? event.screenY - previousEvent.screenY: 0;
                    // var moveX = d3.event.sourceEvent.movementX;
                    // var moveY = d3.event.sourceEvent.movementY;
                    var transform = getFloat(treeG.attr('transform'));
                    var endX = parseFloat(transform[0]? transform[0]:0) + moveX;
                    var endY = parseFloat(transform[1]? transform[1]:0) + moveY;
                    treeG.attr('transform', 'translate(' + endX +','+ endY + ')' +
                        ' scale(' + d3.event.scale + ')');
                    previousEvent = event;
                }else {
                    treeG.attr('transform', 'translate(' + d3.event.translate + ')' +
                        ' scale(' + d3.event.scale + ')');
                    d3.event.translate;
                }
                d3.event.sourceEvent.stopPropagation();
            }

            function disableRightClick() {
                if(d3.event.button == 2) {
                    d3.event.stopImmediatePropagation();
                }
                return tooltip.style('visibility', 'hidden');
            }

            function clearLeftClick() {
                if(d3.event.button == 0) {
                    previousEvent = null;
                }
            }

            function getFloat(value) {
                if (typeof (value)  == 'string') {
                    var regEx = /[^\d|^\.|^\-]/g;
                    value =  value.replace(regEx, ' ').trim();
                    return value.split(/[ ]+/)
                }
                return null;
            }

            function instanceListClick() {
                var deptId = d3.select(this).attr('deptId');
                var status = d3.select(this).attr('status');
                var title = d3.select(this).attr('title');
                status = status ? status:'';
                var url = horizon.paths.syspath + '/manager/flowarea/flowarea.iframe.html?deptId=' + deptId+'&status=' + status;
                modal.open({
                    url: url,
                    title: '['+title +']'+ horizon.lang['flowarea']['instanceList']
                });
            }
        };
        var d3GenerationChart = new treeChart(d3);
        d3GenerationChart.drawChart();
    };
    return horizon.engine['flowarea'] = {
        init: function(obj){
            d3 = obj
            flowMonitor.init();
        }
    };
}));