'use strict'

const
    IDMark_Switch = "_switch",
    IDMark_Icon = "_ico",
    IDMark_Span = "_span",
    IDMark_Input = "_input",
    IDMark_Check = "_check",
    IDMark_Edit = "_edit",
    IDMark_Remove = "_remove",
    IDMark_Ul = "_ul",
    IDMark_A = "_a",
    //以上的常量是在查找zTree默认生成的dom对象时用到（tID + 后缀）

    NODE_LEVEL_COMPILATION_NEW = 1,
    NODE_LEVEL_USER = 0;

let rptTplObj = {
    iniPage: function() {
        zTreeOprObj.getCompilationList();
        rpt_tpl_cfg_helper.getReportTplCfg();
        selectableFiledTreeOprObj.iniTree();
        preview_util.drawBorder($("#tplCanvas")[0]);
        calculationTreeOprObj.buildRunType();
        preHandleObj.buildTypeData();
        calculationTreeOprObj.iniExtCodeTpl();
    }
};

let zTreeOprObj = {
    treeObj: null,
    currentNode: null,
    moveSrcTopNode: null,
    dupTplIds: null,
    hasRefreshedDupRefIds: false,
    getCompilationList: function(){
        let me = zTreeOprObj, params = {};
        CommonAjax.postEx("report_tpl_api/getCompilationList", params, 20000, true, function(result){
                //console.log(result);
                for (let item of result) {
                    // if (item.is_release) {
                        $("#compilations").append("<option value='" + item._id + "'>" + item.name + "</option>");
                    // }
                }
                // me.getReportTemplateTree($("#compilations").get(0));
                me.getReportTemplateTreeEx($("#compilations").get(0));
            }, null, null
        );
    },
    refreshNodes: function() {
        let me = this;
        let private_setupIsParent = function(node){
            // if (node.nodeType === RT.NodeType.NODE || node.level === 0) {
            if (node.nodeType === RT.NodeType.NODE || node.level <= NODE_LEVEL_COMPILATION_NEW) {
                node.isParent = true;
            } else {
                node.isParent = false;
            }
            if (node.items && node.items.length) {
                for (let i = 0; i < node.items.length; i++) {
                    private_setupIsParent(node.items[i]);
                }
            }
        };
        let topNodes = me.treeObj.getNodes();
        for (let i = 0; i < topNodes.length; i++) {
            private_setupIsParent(topNodes[i]);
        }
        me.treeObj.refresh();
    },
    removeTreeRootNode: function(rawNode, isAsync, callback, failCallback) {
        let params = {};
        params.compilationId = rawNode.compilationId;
        params.engineerId = rawNode.engineerId;
        params.userId = rawNode.userId;
        params.isPhysically = true;
        CommonAjax.postEx("report_tpl_api/removeTreeRootNode", params, 5000, isAsync, callback, failCallback, null);
    },
    copyReportTemplate: function(orgID, newID, isAsync, callback, failCallback) {
        let params = {};
        params.orgRptTplId = orgID;
        params.newRptTplId = newID;
        CommonAjax.postEx("report_tpl_api/copyRptTpl", params, 5000, isAsync, callback, failCallback, null);
    },
    updateTreeRootNode: function(rawNode, isAsync, callback, failCallback) {
        let params = {};
        params.doc = rawNode;
        CommonAjax.postEx("report_tpl_api/updateTreeRootNode", params, 5000, isAsync, callback, failCallback, null);
    },
    partialUpdateTreeNode: function (rawNode, pathArray, nodeArray, isAsync, callback, failCallback) {
        // 这个是局部刷新，原理是根据topNodeId找到后台的topNode，根据路径(有多个路径，可以实现多个子节点同时刷新)来替换（nodeArray里的）后台数据库的相关节点
        // 这里需要一个调整，就是新增目录及模板需要加给后缀(new(Date)).getTime() ，以保证不重叠(真重叠了算倒霉)
        // path描述：{ operation_type: '', // 操作类型：‘update’ ‘add’、‘delete’
        //            node_path: [],      // 节点路径：如：['02.广东', '03.增城北绕线项目定制报表']，表示Top节点的items下的那个‘02.广东’子节点(要full scan)的items下的 ‘03.增城北绕线项目定制报表’子节点
        //          }
        // nodeArray： 与pathArray一一对应
        //
        let params = {};
        params.compilationId = rawNode.compilationId;
        params.engineerId = rawNode.engineerId;
        params.userId = rawNode.userId;
        params.pathArray = pathArray;
        params.nodeArray = nodeArray;
        CommonAjax.postEx("report_tpl_api/partialUpdateTreeNode", params, 5000, isAsync, callback, failCallback, null);
    },
    updateTopNodeName: function (topNode, isAsync, callback, failCallback) {
        let params = {};
        params.compilationId = topNode.compilationId;
        params.engineerId = topNode.engineerId;
        params.userId = topNode.userId;
        params.nodeName = topNode.name;
        CommonAjax.postEx("report_tpl_api/updateTopNodeName", params, 5000, isAsync, callback, failCallback, null);
    },
    updateSubNode: function (topNode, subNode, isAsync, callback, failCallback) {
        let params = {};
        params.compilationId = topNode.compilationId;
        params.engineerId = topNode.engineerId;
        params.userId = topNode.userId;
        params.subNode = subNode;
        CommonAjax.postEx("report_tpl_api/updateSubLevelOneNode", params, 5000, isAsync, callback, failCallback, null);
    },
    createIniNode: function() {
        return {
            nodeType: RT.NodeType.TEMPLATE,
            refId: -1,
            name: "",
            ID: -1,
            items: null
        };
    },
    buildRootNodeDoc: function(topNode, excludeNode) {
        let me = this, rst = null;
        if (topNode) {
            rst = {
                compilationId: topNode.compilationId,
                engineerId: topNode.engineerId,
                userId: topNode.userId,
                properties: topNode.properties,
                released: true,
                isDeleted: topNode.isDeleted,
                items: me.private_build_items(topNode.items, excludeNode),
                name: topNode.name
            };
        }
        return rst;
    },
    getNodePath: function(node, includeCurrentNode) {
        const rst = [];
        if (includeCurrentNode && node.level >= 1) {
            rst.push(node.name);
        }
        let parentNode = node.getParentNode();
        while (parentNode && parentNode.level > 0) { //顶节点是dummy的
            rst.unshift(parentNode.name);
            parentNode = parentNode.getParentNode();
            if (parentNode === null || parentNode === undefined || parentNode.level === 0) {
                rst.splice(0,1); // 删除头节点（后台不需要）
            }
        }
        return rst;
    },
    buildSubRootNodeDoc: function(subNode) {
        let me = this, rst = null;
        if (subNode) {
            let isReleased = false;
            if (subNode.nodeType === RT.NodeType.TEMPLATE) {
                isReleased = subNode.checked;
            }
            rst = {
                nodeType: subNode.nodeType,
                refId: subNode.refId,
                ID: subNode.ID,
                released: isReleased,
                items: me.private_build_items(subNode.items, null),
                name: subNode.name
            };
            if (subNode.hasOwnProperty('flags')) {
                rst.flags = subNode.flags;
            }
        }
        return rst;
    },

    private_build_items: function (items, excludeNode) {
        let me = this, itemRst = null;
        if (items && items.length > 0) {
            itemRst = [];
            for (let item of items) {
                if (item !== excludeNode) {
                    let isReleased = false;
                    if (item.nodeType === RT.NodeType.TEMPLATE) {
                        isReleased = item.checked;
                    }
                    let ir = {};
                    ir.nodeType = item.nodeType;
                    ir.refId = item.refId;
                    ir.name = item.name;
                    ir.ID = item.ID;
                    ir.released = isReleased;
                    if (item.hasOwnProperty('flags')) {
                        ir.flags = item.flags;
                    }
                    ir.items = me.private_build_items(item.items);
                    itemRst.push(ir);
                }
            }
        }
        return itemRst;
    },

    addHoverDom: function(treeId, treeNode) {
        let me = zTreeOprObj, sObj = $("#" + treeNode.tId + "_span");
        if (treeNode.editNameFlag || $("#addBtn_"+treeNode.tId).length > 0 || treeNode.nodeType === RT.NodeType.TEMPLATE) return;
        if (treeNode.level === 0) {
            // let addStr = "<span class='button star' id='addBtn_" + treeNode.tId + "' title='新增编办类型' onfocus='this.blur();'></span>";
            // sObj.after(addStr);
            // let btn = $("#addBtn_"+treeNode.tId);
            // if (btn) btn.bind("click", function(){
            //     let rawNode = me.createIniComilationNode();
            //     if (!me.chkIfDupCompilationNode(rawNode, treeNode)) {
            //         rawNode.userId = treeNode.userId;
            //         me.addNewNodeEx(rawNode, function(rst){
            //             if (rst) {
            //                 let newNodes = [], isSilent = false;
            //                 rawNode.isParent = true;
            //                 newNodes.push(rawNode);
            //                 if (treeNode.items && treeNode.items.length > 0) {
            //                     let insertIdx = -1;
            //                     for (let i = 0; i < treeNode.items.length; i++) {
            //                         if (treeNode.items[i].compilationId === rawNode.compilationId) {
            //                             if (treeNode.items[i].engineerId > rawNode.engineerId) {
            //                                 insertIdx = i;
            //                                 break;
            //                             }
            //                         }
            //                     }
            //                     me.treeObj.addNodes(treeNode, insertIdx, newNodes, isSilent);
            //                 } else {
            //                     me.treeObj.addNodes(treeNode, 0, newNodes, isSilent);
            //                 }
            //             } else {
            //                 alert("后台创建失败，请确认是否有重复类型跟节点！")
            //             }
            //         }, null);
            //     } else {
            //         alert("有重复编办！");
            //     }
            // });
        } else {
            let addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='新增子目录' onfocus='this.blur();'></span>";
            sObj.after(addStr);
            let btn = $("#addBtn_"+treeNode.tId);
            if (btn) btn.bind("click", function(){
                me.getNewNodeID(1, function (newNodeID) {
                    let rawNode = me.createIniNode();
                    rawNode.nodeType = RT.NodeType.NODE;
                    rawNode.name = "新增子节点" + (new Date()).getTime();
                    rawNode.ID = newNodeID;
                    rawNode.isParent = true;
                    rawNode.items = [];
                    let newNodes = [], isSilent = false;
                    newNodes.push(rawNode);
                    if (me.treeObj) {
                        let insertIdx = -1;
                        if (treeNode.items && treeNode.items.length > 0) {
                            for (let i = treeNode.items.length - 1; i >= 0; i--) {
                                if (treeNode.items[i].nodeType === RT.NodeType.NODE) {
                                    insertIdx = i + 1;
                                    break;
                                } else {
                                    insertIdx = i;
                                }
                            }
                        }
                        me.treeObj.addNodes(treeNode, insertIdx, newNodes, isSilent);
                        let tn = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
                        let newTopNode = me.buildRootNodeDoc(tn);

                        //*
                        let pathArr = [];
                        let nodeArr = [];
                        let path = {operation_type: 'add', node_path: []};
                        path.node_path = me.getNodePath(treeNode, true);
                        pathArr.push(path);
                        nodeArr.push(rawNode);
                        me.partialUpdateTreeNode(newTopNode, pathArr, nodeArr, true, function(rst){
                            if (!(rst)) {
                                alert("新增节点失败！");
                            }
                            me.refreshNodes();
                        }, null);
                        /*/
                        me.updateTreeRootNode(newTopNode, true, function(rst){
                            if (!(rst)) {
                                alert("新增节点失败！");
                            }
                            me.refreshNodes();
                        }, null);
                        //*/
                    }
                });
            });
            addStr = "<span class='button blue_core' id='addBtn2_" + treeNode.tId + "' title='新增报表模板' onfocus='this.blur();'></span>";
            sObj.after(addStr);
            btn = $("#addBtn2_"+treeNode.tId + "");
            if (btn) btn.bind("click", function(){
                // let me = zTreeOprObj;
                if (treeNode.nodeType === RT.NodeType.NODE || treeNode.level === NODE_LEVEL_COMPILATION_NEW) {
                    me.getNewNodeID(1, function (newNodeID) {
                        let rawNode = me.createIniNode();
                        rawNode.nodeType = RT.NodeType.TEMPLATE;
                        rawNode.name = "新增报表模板" + (new Date()).getTime();
                        rawNode.ID = newNodeID;
                        rawNode.released = false;
                        let newNodes = [], isSilent = false;
                        newNodes.push(rawNode);
                        me.treeObj.addNodes(treeNode, -1, newNodes, isSilent);
                        let tn = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
                        let topNode = me.buildRootNodeDoc(tn);
                        //*
                        let pathArr = [];
                        let nodeArr = [];
                        let path = {operation_type: 'add', node_path: []};
                        path.node_path = me.getNodePath(treeNode, true);
                        pathArr.push(path);
                        nodeArr.push(rawNode);
                        me.partialUpdateTreeNode(topNode, pathArr, nodeArr, true, function(rst){
                            if (!(rst)) {
                                alert("新增节点失败！");
                            }
                            me.refreshNodes();
                        }, null);
                        /*/
                        me.updateTreeRootNode(topNode, true, function(rst){
                            if (!(rst)) {
                                alert("新增空白模板失败！");
                            }
                            me.refreshNodes();
                        }, null);
                        //*/
                    });
                }
            });
        }
    },
    removeHoverDom: function(treeId, treeNode) {
        $("#addBtn_"+treeNode.tId).unbind().remove();
        $("#addBtn2_"+treeNode.tId).unbind().remove();
    },
    addNewNodeEx: function(rawNode, callback, failCallback) {
        let params = {};
        params.doc = rawNode;
        CommonAjax.postEx("report_tpl_api/createTreeRootNode", params, 5000, true, callback, failCallback, null);
    },
    onCheck: function (event, treeId, treeNode) {
        let me = zTreeOprObj;
        let topPNode = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
        let newTopNode = me.buildRootNodeDoc(topPNode);
        me.updateTreeRootNode(newTopNode, true, function(rst){
            if (!(rst)) {
                alert("修改发布状态失败！");
            }
        });
    },
    onBeforeDrag: function (treeId, treeNodes) {
        let rst = true;
        for (let node of treeNodes) {
            if (node.level === 0 || node.nodeType !== RT.NodeType.TEMPLATE) {
                rst = false;
                break;
            }
        }
        return rst;
    },
    onBeforeDrop: function (treeId, treeNodes, targetNode, moveType, isCopy) {
        let me = zTreeOprObj, rst = true;
        let srcNode = treeNodes[0];
        let sourceTopNode = me.getParentNodeByNodeLevel(srcNode, NODE_LEVEL_COMPILATION_NEW);
        let targetTopNode = me.getParentNodeByNodeLevel(targetNode, NODE_LEVEL_COMPILATION_NEW);
        me.moveSrcTopNode = null;
        if (moveType === 'inner') {
            if (targetNode.nodeType === RT.NodeType.TEMPLATE) {
                //模板节点不能成为另一个模板节点的子节点。不过zTree控件默认会处理，这里的代码应该走不到，放在这里以防万一
                rst = false;
            } else {
                if (sourceTopNode !== targetTopNode) {
                    if (!isCopy) {
                        if (!confirm("是否真的要把报表模板移动到另一个工程类型？")) {
                            rst = false;
                        }
                    }
                } else {
                    //同一根节点下，可以随便移动或copy
                }
            }
        } else {
            if (targetNode.level === 0 || targetNode.nodeType !== RT.NodeType.TEMPLATE) {
                //模板节点不能与类型节点或目录节点同级！
                rst = false;
            } else {
                if (sourceTopNode !== targetTopNode) {
                    if (!isCopy) {
                        if (!confirm("是否真的要把报表模板移动到另一个工程类型？")) {
                            rst = false;
                        }
                    }
                } else {
                    //同一根节点下，可以随便移动或copy
                }
            }
        }
        if (rst && !isCopy && sourceTopNode !== targetTopNode) {
            me.moveSrcTopNode = sourceTopNode;
        }
        return rst;
    },
    onDrop: function (event, treeId, treeNodes, targetNode, moveType, isCopy) {
        let me = zTreeOprObj;
        zTreeOprObj.treeObj.checkNode(treeNodes[0], false, false);
        treeNodes[0].released = false;
        let targetTopNode = me.getParentNodeByNodeLevel(targetNode, NODE_LEVEL_COMPILATION_NEW);
        let newTopNode = null;
        let canContinue = false;
        if (isCopy) {
            me.getNewNodeID(1, function (newNodeID) {
                let orgID = treeNodes[0].refId; //refId才是正确的模板ID(因可能copy一个有引用的节点)，
                treeNodes[0].ID = newNodeID;
                if (confirm("是否引用相同的报表模板？")) {
                    newTopNode = me.buildRootNodeDoc(targetTopNode);
                    me.updateTreeRootNode(newTopNode, false, function(goodRst){
                        canContinue = true;
                        if (treeNodes[0].rptTpl) {
                            treeNodes[0].rptTpl.ID = newNodeID;
                        }
                        me.currentNode = treeNodes[0];
                        me.chkAndSetDupRefTplIds(me.treeObj.getNodes(), null);
                        me.treeObj.refresh();
                        me.chkAndRreshRefTpl();
                    }, function(badRst){
                        displayMessage("更新模板节点失败!", "red", 2000);
                        // console.log(badRst.toString());
                        console.log(badRst);
                    });
                } else {
                    treeNodes[0].refId = newNodeID;
                    // targetNode.refId = newNodeID; //targetNode可以是父节点也可以是兄弟节点，没必要引用相同的tplID
                    newTopNode = me.buildRootNodeDoc(targetTopNode);
                    me.copyReportTemplate(orgID, newNodeID, true, function(goodResult){
                        me.updateTreeRootNode(newTopNode, true, function(goodRst){
                            canContinue = true;
                            // treeObj.updateNode(nodes[0]);
                            zTreeOprObj.treeObj.updateNode(treeNodes[0]);
                            if (treeNodes[0].rptTpl) {
                                treeNodes[0].rptTpl.ID = newNodeID;
                            }
                            me.currentNode = treeNodes[0];
                            me.chkAndSetDupRefTplIds(me.treeObj.getNodes(), null);
                            me.treeObj.refresh();
                            me.chkAndRreshRefTpl();
                        }, function(badRst){
                            displayMessage("更新模板节点失败!", "red", 2000);
                            // console.log(badRst.toString());
                            console.log(badRst);
                        });
                    }, function(badResult){
                        displayMessage("Copy请求失败!", "red", 2000);
                        // console.log(badResult.toString());
                        console.log(badResult);
                    });
                }
            });
            // if (canContinue) {
            //     me.chkAndRreshRefTpl();
            // }
        } else {
            newTopNode = me.buildRootNodeDoc(targetTopNode);
            me.updateTreeRootNode(newTopNode, false, function(rst){
                canContinue = true;
                me.currentNode = treeNodes[0];
            }, function(badResult){
                displayMessage("移动请求失败!", "red", 2000);
                console.log(badResult.toString());
                canContinue = false;
            });
            if (canContinue && !isCopy && me.moveSrcTopNode) {
                let newSrcTopNode = me.buildRootNodeDoc(me.moveSrcTopNode);
                me.updateTreeRootNode(newSrcTopNode, true, function(rst){
                    // canContinue = true;
                }, function(badResult){
                    displayMessage("移动请求失败!", "red", 2000);
                    canContinue = true;
                });
            }
            me.moveSrcTopNode = null;
        }
    },
    addReportTemplate: function(newUsers) {
        let me = zTreeOprObj, params = {};
        params.compilationId = $("#compilations").get(0).value;
        params.userId = [];
        if (newUsers.length > 0) {
            for (let user of newUsers) {
                params.userId.push(user.userId);
            }
        }
        let allEngIds = [];
        for (let item of engineeringList) {
            allEngIds.push(item.value);
        }
        params.engineerId = allEngIds;
        CommonAjax.postEx("report_tpl_api/getRptTplTree", params, 20000, true, function(result){
            result.sort(function(item1, item2){
                let rst = 0;
                if (item1.userId === item2.userId) {
                    rst = (item1.engineerId > item2.engineerId)?1:((item1.engineerId < item2.engineerId)?-1:0);
                } else {
                    if (item1.userId === "-100") {
                        rst = 1
                    } else if (item2.userId === "-100") {
                        rst = -1
                    } else {
                        let idx1 = -1, idx2 = -1;
                        for (let uidx = 0; uidx < newUsers.length; uidx++) {
                            if (newUsers[uidx].userId === item1.userId) idx1 = uidx;
                            if (newUsers[uidx].userId === item2.userId) idx2 = uidx;
                            if (idx1 >= 0 && idx2 >= 0) {
                                break;
                            }
                            rst = (idx1 > idx2)?1:((idx1 < idx2)?-1:0);
                        }
                    }
                }
                return rst;
            });
            let allTopUserIdNodes = [];
            let allTopTplNodes = [];
            for (let user of newUsers) {
                allTopUserIdNodes.push(user.userId);
                allTopTplNodes.push({userId: user.userId, name: user.real_name, items: [], isParent: true});
            }
            for (let item of result) {
                let uidx = allTopUserIdNodes.indexOf(item.userId);
                if (uidx >= 0) {
                    item.isParent = true;
                    allTopTplNodes[uidx].items.push(item);
                }
            }
            // zTreeHelper.createTreeDirectly(allTopTplNodes, setting, "rptTplTree", me);
            //add template nodes
            let isSilent = false;
            me.treeObj.addNodes(null, -1, allTopTplNodes, isSilent);
            me.refreshNodes();
            let private_setup_checked = function (itemNode) {
                if (itemNode.nodeType === RT.NodeType.NODE) {
                    me.treeObj.setChkDisabled(itemNode, true);
                } else if (itemNode.nodeType === RT.NodeType.TEMPLATE) {
                    me.treeObj.checkNode(itemNode, !!(itemNode.released));
                }
                if (itemNode.items && itemNode.items.length > 0) {
                    for (let subItem of itemNode.items) {
                        private_setup_checked(subItem);
                    }
                }
            };
            let topNodes = me.treeObj.getNodes();
            // me.treeObj.expandAll(true);
            for (let node of topNodes) {
                me.treeObj.setChkDisabled(node, true);
                if (node.items && node.items.length > 0) {
                    for (let item of node.items) {
                        me.treeObj.setChkDisabled(item, true);
                        private_setup_checked(item);
                    }
                }
            }
        }, null, null);
    },
    chkAndSetDupRefTplIds: function (tplNodes, selectedRefId) {
        let me = zTreeOprObj, tmpRefIds = [];
        me.dupTplIds = [];
        let private_get_dup_ids = function (tplNode) {
            if (tplNode.refId && tplNode.refId !== -1) {
                let refId = tplNode.refId;
                if (tmpRefIds.indexOf(refId) < 0) {
                    tmpRefIds.push(refId);
                } else {
                    if (me.dupTplIds.indexOf(refId) < 0) {
                        me.dupTplIds.push(refId);
                    } else {
                        //
                    }
                }
            }
            if (tplNode.items && tplNode.items.length > 0) {
                for (let subTplNode of tplNode.items) {
                    private_get_dup_ids(subTplNode);
                }
            }
        };
        let private_set_dup_icon = function (tplNode) {
            if (me.dupTplIds.indexOf(tplNode.refId) >= 0) {
                // tplNode.icon = "../../../../lib/ztree/css/img/diy/3.png"; //or below:
                if (selectedRefId && selectedRefId === tplNode.refId) {
                    tplNode.icon = "/lib/ztree/css/img/diy/5.png";
                } else {
                    tplNode.icon = "/lib/ztree/css/img/diy/3.png";
                }
                // tplNode.style = "background:url(/lib/ztree/css/img/diy/3.png) 0 0 no-repeat;"
            } else {
                //设置白板
                // if (!tplNode.isParent) tplNode.icon = "/lib/ztree/css/img/diy/10.png";
                if (!tplNode.isParent) tplNode.className = "button ico_docu";
            }
            if (tplNode.items && tplNode.items.length > 0) {
                for (let subTplNode of tplNode.items) {
                    private_set_dup_icon(subTplNode);
                }
            }
        };
        for (let tplNodeItem of tplNodes) {
            private_get_dup_ids(tplNodeItem);
        }
        for (let tplNodeItem of tplNodes) {
            private_set_dup_icon(tplNodeItem);
        }
        if (selectedRefId) {
            me.hasRefreshedDupRefIds = true;
        } else {
            me.hasRefreshedDupRefIds = false;
        }
    },
    getReportTemplateTreeEx: function (compilationSelect) {
        let me = zTreeOprObj, params = {};
        params.compilationId = compilationSelect.value;
        CommonAjax.postEx("report_tpl_api/getTplTreeByCompilation", params, 20000, true, function(result){
            result.sort(function(item1, item2){
                let rst = 0;
                if (item1.userId === "-100") {
                    rst = -1;
                } else if (item2.userId === "-100") {
                    rst = 1;
                }
                return rst;
            });
            // me.chkAndSetDupRefTplIds(result);
            // console.log(dupRefIds);
            let allTopTplNodes = [{userId: "-100", name: "公共模板", items:[], isParent: true, refId: ""}];
            if (result.length > 0) {
                if (!result[0].hasOwnProperty("refId")) {
                    result[0].refId = "";
                }
                allTopTplNodes[0].items.push(result[0]);
            }
            let userIds = [];
            for (let idx = 1; idx < result.length; idx++) {
                let item = result[idx];
                if (!item.hasOwnProperty("refId")) {
                    item.refId = "";
                }
                userIds.push(item.userId);
            }
            userListObj.findUsersByIds(userIds, function (userObjs) {
                for (let user of userObjs) {
                    for (let itemIdx = 1; itemIdx < result.length; itemIdx++) {
                        let item = result[itemIdx];
                        if (item.userId === user._id) {
                            allTopTplNodes.push({userId: user.userId, name: user.real_name, items: [], isParent: true, refId: ""});
                            allTopTplNodes[allTopTplNodes.length - 1].items.push(result[itemIdx]);
                            break;
                        }
                    }
                }
                zTreeHelper.createTreeDirectly(allTopTplNodes, setting, "rptTplTree", me);
                let topNodes = me.treeObj.getNodes();
                me.chkAndSetDupRefTplIds(topNodes, null);
                me.refreshNodes();
                let private_setup_checked = function (itemNode) {
                    if (itemNode.nodeType === RT.NodeType.NODE) {
                        me.treeObj.setChkDisabled(itemNode, true);
                    } else if (itemNode.nodeType === RT.NodeType.TEMPLATE) {
                        me.treeObj.checkNode(itemNode, !!(itemNode.released));
                    }
                    if (itemNode.items && itemNode.items.length > 0) {
                        for (let subItem of itemNode.items) {
                            private_setup_checked(subItem);
                        }
                    }
                };
                me.treeObj.expandAll(true);
                for (let node of topNodes) {
                    me.treeObj.setChkDisabled(node, true);
                    if (node.items && node.items.length > 0) {
                        for (let item of node.items) {
                            me.treeObj.setChkDisabled(item, true);
                            private_setup_checked(item);
                        }
                    }
                }
            });
        }, null, null);
    },
    getNewNodeID: function (scope, callback) {
        let params = {};
        params.scope = scope;
        CommonAjax.postEx("report_tpl_api/getNewNodeID", params, 5000, true, callback, null, null);
    },
    chkIfDupCompilationNode: function (rawNode, parentUserNode) {
        let rst = false;
        //在新的需求下，只需要检测编办与userId即可，无需工程id
        if (parentUserNode.items && parentUserNode.items.length > 0) {
            for (let node of parentUserNode.items) {
                if (node.compilationId === rawNode.compilationId && node.userId === rawNode.userId) {
                    rst = true;
                    break;
                }
            }
        }
        return rst;
    },
    createIniComilationNode: function() {
        //在新的需求下，无需工程id
        let rst = {
            compilationId: $("#compilations").get(0).selectedOptions[0].value,
            userId: (userAccount ===  'admin')?("-100"):userID,
            properties: [],
            released: true,
            isDeleted: false,
            items: [],
            name: $("#compilations").get(0).selectedOptions[0].innerText
        };
        return rst;
    },
    onBeforeRemove: function(treeId, treeNode){
        let canRemove = false;
        if (treeNode.level > NODE_LEVEL_USER) {
            if (!(treeNode.items) || treeNode.items.length < 1) {
                canRemove = confirm("请再确认您要删除！");
            } else {
                alert("含有子项，不能删除！");
            }
        } else {
            alert("不能删除用户级别模板！");
        }
        return canRemove;
    },
    onRemove: function(e, treeId, treeNode){
        if (treeNode.level > NODE_LEVEL_USER) {
            let me = zTreeOprObj,
                topPNode = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
            let rawNode = me.buildRootNodeDoc(topPNode, treeNode);
            if (treeNode.level === NODE_LEVEL_COMPILATION_NEW) {
                me.removeTreeRootNode(rawNode, true, function(rst){
                    if (!(rst)) {
                        alert("删除请求失败！");
                    }
                });
            } else {
                // me.updateTreeRootNode(rawNode, true, function(rst){
                //     if (!(rst)) {
                //         alert("删除请求失败！");
                //     }
                // });
                let pathArr = [];
                let nodeArr = [];
                let path = {operation_type: 'delete', node_path: []};
                path.node_path = me.getNodePath(treeNode, true);
                pathArr.push(path);
                nodeArr.push('');
                me.partialUpdateTreeNode(topPNode, pathArr, nodeArr, true, function (rst) {
                    if (!(rst)) {
                        alert("删除模板失败！");
                    }
                }, null);
            }
            me.refreshNodes();
            //*/
        }
    },
    beforeEditName: function (treeId, treeNode) {
        if (treeNode.level > NODE_LEVEL_COMPILATION_NEW) {
            setTimeout(function(){
                let ip = $("#" + treeNode.tId + IDMark_Input);
                if (ip.length > 0) {
                    ip[0].className = "individualRename";
                } else {
                    setTimeout(function(){
                        let ip = $("#" + treeNode.tId + IDMark_Input);
                        if (ip.length > 0) {
                            ip[0].className = "individualRename";
                        } else {
                            console.log("sorry!");
                        }
                    }, 50);
                }
            }, 50);
            return true;
        } else {
            return false;
        }
    },
    beforeRename: function(treeId, treeNode, newName, isCancel) {
        if (newName.length === 0) {
            return false;
        }
        return true;
    },
    onRename : function(e, treeId, treeNode, isCancel) {
        if (!isCancel) {
            let me = zTreeOprObj;
            if (treeNode.level === 0) {
                //因结构变化，已经不允许更改顶节点名字
            } else {
                let subTopNode = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW + 1);
                let topPNode = subTopNode.getParentNode();
                let rawNode = me.buildSubRootNodeDoc(subTopNode);
                me.updateSubNode(topPNode, rawNode, true, function(rst){
                    if (!(rst)) {
                        alert('修改名称请求失败！');
                    }
                });
            }
        }
    },
    onChangeFlag: function(flagProp, flagDom){
        let me = zTreeOprObj;
        if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE) {
            if (!me.currentNode.hasOwnProperty("flags")) {
                me.currentNode.flags = {};
            }
            me.currentNode.flags[flagProp] = (flagDom.selectedOptions[0].value === 'NA')?null:flagDom.selectedOptions[0].value;
            let subTopNode = me.getParentNodeByNodeLevel(me.currentNode, NODE_LEVEL_COMPILATION_NEW + 1);
            let topPNode = subTopNode.getParentNode();
            let rawNode = me.buildSubRootNodeDoc(subTopNode);
            me.updateSubNode(topPNode, rawNode, true, function(rst){
                if (!(rst)) {
                    alert('修改标记：[' + flagProp + '] 失败！');
                }
            });
        }
    },

    createNewTpl: function () {
        let me = zTreeOprObj, params = {};
        if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE) {
            params.treeNodeId = me.currentNode.ID;
            let rptTypeId = common_rpt_type_ids.flow;
            if ($("#crossTypeOpt")[0].checked) rptTypeId = common_rpt_type_ids.cross;
            if ($("#billTypeOpt")[0].checked) rptTypeId = common_rpt_type_ids.bill;
            params.rptDftTplId = rptTypeId;
            params.rptName = me.currentNode.name;
            params.grpKey = me.getFolderText(me.currentNode, "_");
            me.currentNode.refId = me.currentNode.ID;
            let subTopNode = me.getParentNodeByNodeLevel(me.currentNode, NODE_LEVEL_COMPILATION_NEW + 1);
            let topPNode = me.getParentNodeByNodeLevel(subTopNode, NODE_LEVEL_COMPILATION_NEW);
            let rawNode = me.buildSubRootNodeDoc(subTopNode);
            params.compilationId = topPNode.compilationId;
            params.engineerId = topPNode.engineerId;
            params.userId = topPNode.userId;
            params.subNode = rawNode;
            CommonAjax.postEx("report_tpl_api/createDftRptTpl", params, 10000, true, function(result){
                    if (result) {
                        me.currentNode.rptTpl = result;
                        me.chkAndRreshRefTpl();
                    } else {
                        alert('update error!');
                    }
                }, null, null
            );
        }
    },
    beforeClick: function (treeId, treeNode, clickFlag) {
        let me = zTreeOprObj;
        if (me.dupTplIds && me.dupTplIds.indexOf(treeNode.refId) >= 0) {
            let topNodes = me.treeObj.getNodes();
            me.chkAndSetDupRefTplIds(topNodes, treeNode.refId);
            me.refreshNodes();
        } else if (me.hasRefreshedDupRefIds) {
            let topNodes = me.treeObj.getNodes();
            me.chkAndSetDupRefTplIds(topNodes, null);
            me.refreshNodes();
        }
        return true;
    },
    onClick: function(event,treeId,treeNode) {
        let me = zTreeOprObj;
        me.currentNode = treeNode;
        bandTreeOprObj.currentNode = null;
        if (treeNode.nodeType === RT.NodeType.NODE) {
            $("#rpt_tpl_display_label")[0].innerText = "...";
        } else if (treeNode.nodeType === RT.NodeType.TEMPLATE) {
            let showText = me.getFolderText(me.currentNode, " > ");
            $("#rpt_tpl_display_label")[0].innerText = showText;
            if (treeNode.refId < 0) {
                //创建新报表模板
                $('#rptTypeSelectionModal').modal('show');
            } else {
                //显示报表模板
                me.chkAndRreshRefTpl(true);
            }
        }
    },
    isFlowTpl: function () {
        let rst = false;
        let me = zTreeOprObj;
        if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE) {
            rst = !!(me.currentNode.rptTpl[JV.NODE_FLOW_INFO]);
        }
        return rst;
    },
    isCrossTpl: function () {
        let rst = false;
        let me = zTreeOprObj;
        if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE) {
            rst = !!(me.currentNode.rptTpl[JV.NODE_CROSS_INFO]);
        }
        return rst;
    },
    isBillTpl: function () {
        let rst = false;
        let me = zTreeOprObj;
        if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE) {
            rst = !!(me.currentNode.rptTpl[JV.NODE_BILL_INFO]);
        }
        return rst;
    },
    getFolderText: function (treeNode, separator) {
        let rst = "";
        if (treeNode) {
            rst = treeNode.name;
            let parentNode = treeNode.getParentNode();
            while (parentNode !== null) {
                rst = parentNode.name + separator + rst;
                parentNode = parentNode.getParentNode();
            }
        }
        return rst;
    },
    chkAndRreshRefTpl: function(forceRefresh) {
        let me = zTreeOprObj, params = {};
        if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE && me.currentNode.refId > 0) {
            if (forceRefresh || !(me.currentNode.rptTpl)) {
                params.rptTplId = me.currentNode.refId;
                CommonAjax.postEx("report_tpl_api/getRefRptTpl", params, 20000, true, function(result){
                        me.currentNode.rptTpl = result;
                        me.currentNode.rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MAIN_INFO_RPT_NAME] = me.currentNode.name;
                        if (me.currentNode.rptTpl["GROUP_KEY"]) {
                            let grp_keys = me.currentNode.rptTpl["GROUP_KEY"].split('_');
                            if (grp_keys.length > 0) {
                                grp_keys[1] = me.currentNode.name;
                            }
                            me.currentNode.rptTpl["GROUP_KEY"] = grp_keys.join("_");
                        }
                        tplHelper.refreshTplView(me.currentNode.rptTpl);
                        if (me.currentNode.hasOwnProperty('flags')) {
                            if (me.currentNode.flags.hasOwnProperty('taxType')) {
                                let val = parseInt(me.currentNode.flags['taxType']);
                                $("#element_flags_select")[0].selectedIndex = val;
                            } else {
                                $("#element_flags_select")[0].selectedIndex = 0;
                            }
                        } else {
                            $("#element_flags_select")[0].selectedIndex = 0;
                        }

                        if ($("#rpt_tpl_visual_tab")[0].className === "nav-link p-1 active") {
                            setTimeout(function(){visualJumbo.iniSpreadJs(); visualJumbo.setupTpl()}, 50)
                        }
                    }, null, null
                );
            } else {
                me.currentNode.rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MAIN_INFO_RPT_NAME] = me.currentNode.name;
                tplHelper.refreshTplView(me.currentNode.rptTpl);
                if ($("#rpt_tpl_visual_tab")[0].className === "nav-link p-1 active") {
                    setTimeout(function(){visualJumbo.iniSpreadJs(); visualJumbo.setupTpl()}, 50)
                }
            }
        }
    },
    getRefTpl: function() {
        let me = zTreeOprObj, rst = null;
        if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE && me.currentNode.refId > 0) {
            rst = me.currentNode.rptTpl
        }
        return rst;
    },
    changeProperty: function (propStr, dom) {
        let me = zTreeOprObj;
        if (me.currentNode && me.currentNode.rptTpl) {
            let props = propStr.split('.');
            let lastProp = me.currentNode.rptTpl;
            for (let idx = 1; idx < props.length; idx++) {
                lastProp = lastProp[props[idx - 1]];
            }
            lastProp[props[props.length - 1]] = dom.value;
        }
    },
    extractMainInfo: function (rptTpl) {
        //模板信息
        rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MAIN_INFO_RPT_NAME] = $("#rptTplName")[0].value;
        rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_PAGE_SIZE] = JV.PAGES_SIZE_STR[$("#rptTplPageSize")[0].selectedIndex];
        if ($("#rptTplPageOrientation")[0].selectedIndex === 1) {
            rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_ORIENTATION] = JV.ORIENTATION_PORTRAIT;
        } else {
            rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_ORIENTATION] = JV.ORIENTATION_LANDSCAPE;
        }
        if (rptTpl[JV.NODE_FLOW_INFO]) {
            rptTpl[JV.NODE_FLOW_INFO][JV.PROP_MULTI_COLUMN] = parseInt($("#rptTplMultiCols")[0].value);
        }
        //考虑到页边距必然跟用户设置走，所以这里没必要特意去设置了，全部下架
    },
    getParentNodeByNodeLevel: function (currentNode, level) {
        let rst = currentNode;
        while (rst !== null) {
            if (rst.level <= level) {
                break;
            } else {
                rst = rst.getParentNode();
            }
        }
        return rst;
    }
};

let userListObj = {
    foundedUserList: [],
    UserIdList: [],
    pushUser: function(user, newUsers) {
        let me = userListObj;
        if (me.UserIdList.indexOf(user._id) < 0) {
            me.UserIdList.push(user._id);
            let newUser = {userId: user._id, real_name: user.real_name, username: user.username, mobile: user.mobile};
            me.foundedUserList.push(newUser);
            if (newUsers) {
                newUsers.push(newUser);
            }
        }
    },
    findUser: function () {
        let key = $("#rpt_user_input1").get(0).value;
        let newUsers = [];
        $.ajax({
            type:"GET",
            url: "user/search?keyword=" + key,
            cache: false,
            timeout: 5000,
            success: function(result){
                if (result.data && result.data.length > 0) {
                    for (let user of result.data) {
                        userListObj.pushUser(user, newUsers);
                    }
                    if (newUsers.length > 0) {
                        zTreeOprObj.addReportTemplate(newUsers);
                    }
                }
            },
            error: function(jqXHR, textStatus, errorThrown){
            }
        });
    },
    findUsersByIds: function (userIds, cb) {
        let params = {};
        params.userIds = userIds;
        CommonAjax.postEx("user/getUserList", params, 20000, true, function(result){
                for (let user of result) {
                    userListObj.pushUser(user, null);
                }
                if (cb) {
                    cb(result);
                }
            }, null, null
        );
    }
};

function displayMessage(message, color, disappearTime, id) {
    let domId = id;
    if (!domId) domId = "id_after_saved_lbl";
    $("#" + domId)[0].style.color = color;
    $("#" + domId)[0].innerHTML = message;
    setTimeout(function(){
        $("#" + domId)[0].innerHTML = "";
    }, disappearTime);
}