/**
 * Created by vian on 2017/4/12.
 */
var dbController = {
    controller: null,
    currentEditData: null,
    insert: function(controller, btn){
        tools.btnClose(btn);
        btn.attr('doing', 'true');
        if(controller.tree.items.length === 0){
            controller.tree.maxNodeID(0);
            let newNodeId = uuid.v1();
            let sectionInfo = {first: null, second: null, third: null};
            billsAjax.createBills(userAccount, billsLibId, newNodeId, -1 , -1, null, sectionInfo, function(){
                controller.insertByID(newNodeId);
                controller.tree.selected.jobs = new Array();
                controller.tree.selected.items = new Array();
                controller.sheet.setTag(controller.tree.selected.serialNo(), 0, newNodeId);
                sheetBillsDatas = tools.getsheetDatas(controller.sheet, 'bills', controller);
                tools.btnAction(btn);
                btn.attr('doing', 'false');
                controller.sheet.getParent().focus(true);
            });
        }
        else {
            let node = controller.tree.selected;
            if(node){
                var updateId = node.getID(), createpid = node.getParentID(), createnid = node.getNextSiblingID();
                let newNodeId = uuid.v1();
                let updatePreData = {ID: updateId, NextSiblingID: newNodeId};
                let sectionInfo = tools.getSectionInfo(node);
                billsAjax.createBills(userAccount, billsLibId, newNodeId, createpid, createnid, updatePreData, sectionInfo, function(){
                    controller.insertByID(newNodeId);
                    controller.tree.selected.jobs = new Array();
                    controller.tree.selected.items = new Array();
                    controller.sheet.setTag(controller.tree.selected.serialNo(), 0, newNodeId);
                    sheetBillsDatas = tools.getsheetDatas(controller.sheet, 'bills', controller);
                    tools.btnAction(btn);
                    btn.attr('doing', 'false');
                    controller.sheet.getParent().focus(true);
                });
            }
            else {
                let updateNode = controller.tree.roots[controller.tree.roots.length - 1];
                let updateId = updateNode.getID();
                //let newNodeId = controllers.tree.newNodeID();
                let newNodeId = uuid.v1();
                let updatePreData = {ID: updateId, NextSiblingID: newNodeId};
                let sectionInfo = tools.getSectionInfo(node);
                billsAjax.createBills(userAccount, billsLibId, newNodeId, -1, -1, updatePreData, sectionInfo, function(){
                    controller.insertByID(newNodeId);
                    controller.tree.selected.jobs = new Array();
                    controller.tree.selected.items = new Array();
                    controller.sheet.setTag(controller.tree.selected.serialNo(), 0, newNodeId);
                    sheetBillsDatas = tools.getsheetDatas(controller.sheet, 'bills', controller);
                    tools.btnAction(btn);
                    btn.attr('doing', 'false');
                    controller.sheet.getParent().focus(true);
                });
            }
        }
    },

    upLevel: function(controller, btn){
        tools.btnClose(btn);
        btn.attr('doing', 'true');
        var node = controller.tree.selected;
        var nextSiblingIds = [];
        var updateData = [];
        let selNodes = tools.getSameDepthNodes(controller);
        let nextSiblings = [];
        let toUpSectionNodes = [];
        let getNextSibling = function(node){
            if(node.nextSibling){
                nextSiblingIds.push(node.getNextSiblingID());
                nextSiblings.push(node.nextSibling);
                getNextSibling(node.nextSibling);
            }
        };
        if(selNodes.length > 0){
            let firstParent = selNodes[0].parent;
            //选中的第一个节点有父节点，则可升级
            if(firstParent){
                //更新父节点
                updateData.push({
                    ID: firstParent.getID(),
                    NextSiblingID: selNodes[0].getID(),
                    type: 'parentNode'
                });
                //更新前节点
                if(selNodes[0].preSibling){
                    updateData.push({
                        ID: selNodes[0].preSibling.getID(),
                        NextSiblingID: -1,
                        type: 'preSiblingNode'
                    });
                }
                //更新选中节点的后兄弟节点
                let lastSelNode = selNodes[selNodes.length - 1];
                if(lastSelNode.nextSibling){
                    let nextSectionInfo = tools.getSectionInfo(firstParent);
                    let nullNextSectionInfo = tools.sectionInfoNull(nextSectionInfo);
                    if(nullNextSectionInfo){
                        nextSectionInfo[nullNextSectionInfo] = lastSelNode.getID();
                    }
                    getNextSibling(lastSelNode);
                    updateData.push({
                        ID: nextSiblingIds,
                        ParentID: lastSelNode.getID(),
                        //sectionInfo: nextSectionInfo,
                        type: 'nextSiblingNode'
                    });
                    //nextSibling children
                }
                //更新选中节点
                for(let i = 0; i < selNodes.length; i++){
                    let selNode = selNodes[i];
                    let oprSectionInfo = tools.getSectionInfo(firstParent);
                    updateData.push({
                        ID: selNode.getID(),
                        ParentID: firstParent.getParentID(),
                        NextSiblingID: i === selNodes.length - 1 ? firstParent.getNextSiblingID() : selNode.getNextSiblingID(),
                        sectionInfo: oprSectionInfo,
                        type: 'oprNode'
                    });
                    //update node children and grandchildren sectionInfo
                }
                //get updateSectionInfo nodes
                toUpSectionNodes = toUpSectionNodes.concat(selNodes);//选中的节点
                //选中节点的所有子节点
                toUpSectionNodes = toUpSectionNodes.concat(tools.getChildrenNodes(selNodes));
                //后兄弟节点
                toUpSectionNodes = toUpSectionNodes.concat(nextSiblings);
                //所有后兄弟节点的所有子节点
                toUpSectionNodes = toUpSectionNodes.concat(tools.getChildrenNodes(nextSiblings));

                billsAjax.upLevel(userAccount, billsLibId, updateData, function(){
                    //tools.btnAction(btn);
                    //btn.attr('doing', 'false');
                    for(let upLevelNode of selNodes){
                        controller.setTreeSelected(upLevelNode);
                        controller.upLevel();
                    }
                    sheetBillsDatas = tools.getsheetDatas(controller.sheet, 'bills', controller);
                    controller.sheet.getParent().focus(true);
                    //updateSectionInfo
                    if(toUpSectionNodes.length > 0){
                        billsAjax.updateSectionInfo(tools.getUpdateSectionData(toUpSectionNodes), function () {
                            tools.btnAction(btn);
                            btn.attr('doing', 'false');
                        });
                    }
                });
            }
        }
    },

    downLevel: function(controller, btn){
        tools.btnClose(btn);
        btn.attr('doing', 'true');
        var updateData = [];
        let selNodes = tools.getSameDepthNodes(controller);
        let toUpSectionNodes = [];
        if(selNodes.length > 0){
            //选中的第一个节点有前节点，则可降级
            let firstPreSibling = selNodes[0].preSibling;
            if(firstPreSibling){
                //更新前节点
                updateData.push({
                    ID: firstPreSibling.getID(),
                    NextSiblingID: selNodes[selNodes.length - 1].getNextSiblingID(),
                    type: 'preSiblingNode'});
                //更新前节点最末子节点
                if(firstPreSibling.children.length > 0){
                    updateData.push({
                        ID: firstPreSibling.children[firstPreSibling.children.length - 1].getID(),
                        NextSiblingID: selNodes[0].getID(),
                        type: 'preChildren'
                    })
                }
                for(let i = 0; i < selNodes.length; i++){
                    let selNode = selNodes[i];
                    //更新选中的节点
                    updateData.push({
                        ID: selNode.getID(),
                        ParentID: firstPreSibling.getID(),
                        NextSiblingID: i === selNodes.length - 1 ? -1 : selNode.getNextSiblingID(),
                        type: 'oprNode'});
                }

                //get updateSectionInfo nodes
                //选中的节点
                toUpSectionNodes = toUpSectionNodes.concat(selNodes);
                //选中节点的所有子节点
                toUpSectionNodes = toUpSectionNodes.concat(tools.getChildrenNodes(selNodes));

                billsAjax.downLevel(userAccount, billsLibId, updateData, function(){
                    //tools.btnAction(btn);
                    //btn.attr('doing', 'false');
                    for(let downNode of selNodes){
                        controller.setTreeSelected(downNode);
                        controller.downLevel();
                    }
                    sheetBillsDatas = tools.getsheetDatas(controller.sheet, 'bills', controller);
                    controller.sheet.getParent().focus(true);
                    //update sectionInfo
                    if(toUpSectionNodes.length > 0){
                        billsAjax.updateSectionInfo(tools.getUpdateSectionData(toUpSectionNodes), function () {
                            tools.btnAction(btn);
                            btn.attr('doing', 'false');
                        });
                    }
                });
            }
        }
    },

    delete: function(controller, btn, totalJobs, totalItems){
        tools.btnClose(btn);
        btn.attr('doing', 'true');
        var node = controller.tree.selected;
        if(node){
            var deleteIds = [];
            var getDeleteIds = function(node){
                if(node){
                    deleteIds.push(node.getID());
                    var length = node.children.length;
                    if(length > 0){
                        for(var i=0; i<length; i++){
                            getDeleteIds(node.children[i]);
                        }
                    }
                }
            };
            getDeleteIds(node);
            let updateNode = node.preSibling ? {ID: node.preSibling.getID(), NextSiblingID: node.getNextSiblingID()} : null;
            billsAjax.deleteBills(userAccount, billsLibId, deleteIds, updateNode, function(){
                tools.btnAction(btn);
                btn.attr('doing', 'false');
                controller.delete();
                //to solve refresh after deleted
                let jobsSheet = jobsSpread.getActiveSheet();
                let itemsSheet = itemsSpread.getActiveSheet();
                let nowNode = controller.tree.selected ;
                if(nowNode){
                    let jobs = controller.tree.selected.jobs;
                    const recharge = controller.tree.selected.data.recharge || '';
                    codeEditor.setValue(recharge);
                    //$('#exampleTextarea').val(controller.tree.selected.data.recharge);
                    setSheet.setMaxRowCount(jobsSheet, jobs);
                    tools.orderReshowData(jobsSheet, jobs, jobsSetting, 'job', false);
                    if(jobs.length > 0){
                        orgJobData = jobsSheet.getValue(0, 0);
                    }
                    let items = controller.tree.selected.items;
                    setSheet.setMaxRowCount(itemsSheet, items);
                    tools.orderReshowData(itemsSheet, items, itemsSetting, 'item', false);
                    if(items.length > 0){
                        orgItemData = itemsSheet.getValue(0, 0);
                    }
                }
                else {
                    tools.clearData(jobsSheet);
                    tools.clearData(itemsSheet);
                    codeEditor.setValue('');
                    //$('#exampleTextarea').val("");
                }
                sheetDatas = tools.getsheetDatas(jobsSheet, 'jobs');
                sheetItemsDatas = tools.getsheetDatas(itemsSheet, 'items');
                sheetBillsDatas = tools.getsheetDatas(controller.sheet, 'bills', controller);
                controller.sheet.getParent().focus(true);
                //to solve refresh after deleted
            });
        }
    },

    upMove: function(controller, btn){
        tools.btnClose(btn);
        btn.attr('doing', 'true');
        var node = controller.tree.selected;
        var updateData = [];
        if(node){
            if(node.preSibling){
                let updateA = {
                    ID: node.preSibling.getID(),
                    NextSiblingID: node.getNextSiblingID()
                };
                let updateB = {
                    ID: node.getID(),
                    NextSiblingID: node.preSibling.getID()
                };
                updateData.push(updateA);
                updateData.push(updateB);
                if(node.preSibling.preSibling){
                    let updateC = {
                        ID: node.preSibling.preSibling.getID(),
                        NextSiblingID: node.getID()
                    }
                    updateData.push(updateC);
                }
                billsAjax.upMove(userAccount, billsLibId, updateData, function(){
                    tools.btnAction(btn);
                    btn.attr('doing', 'false');
                    controller.upMove();
                    //udpate tag
                    controller.sheet.setTag(controller.tree.selected.serialNo(), 0, controller.tree.selected.getID());
                    controller.sheet.setTag(controller.tree.selected.nextSibling.serialNo(), 0, controller.tree.selected.nextSibling.getID());
                    sheetBillsDatas = tools.getsheetDatas(controller.sheet, 'bills', controller);

                    controller.sheet.getParent().focus(true);
                });
            }
        }
    },

    downMove: function(controller, btn){
        tools.btnClose(btn);
        btn.attr('doing', 'true');
        var node = controller.tree.selected;
        var updateData = [];
        if(node){
            if(node.nextSibling){
                var updateA = {
                    ID: node.getNextSiblingID(),
                    NextSiblingID: node.getID(),
                    type: 'nextSiblingNode'
                };
                var updateB = {
                    ID: node.getID(),
                    NextSiblingID: node.nextSibling.getNextSiblingID(),
                    type: 'oprNode'
                };
                updateData.push(updateA);
                updateData.push(updateB);
                if(node.preSibling){
                    var updateC = {
                        ID: node.preSibling.getID(),
                        NextSiblingID: node.getNextSiblingID(),
                        type: 'preSiblingNode'
                    };
                    updateData.push(updateC);
                }
                billsAjax.downMove(userAccount, billsLibId, updateData);
                tools.btnAction(btn);
                btn.attr('doing', 'false');
                controller.downMove();
                //udpate tag
                controller.sheet.setTag(controller.tree.selected.serialNo(), 0, controller.tree.selected.getID());
                controller.sheet.setTag(controller.tree.selected.preSibling.serialNo(), 0, controller.tree.selected.preSibling.getID());
                sheetBillsDatas = tools.getsheetDatas(controller.sheet, 'bills', controller);
                controller.sheet.getParent().focus(true);
            }
        }
    },
    onEditStart: function (sender, args) {
        dbController.currentEditData = args.sheet.getValue(args.row, args.col);
    },
    onEditEnded: function (sender, args) {
        let controller = dbController.controller;
        var node = controller.tree.items[args.row], updateId, field;
        if(node){
            updateId = node.getID();
            field = billsLibSetting.cols[args.col].data.field;
            if(field === 'engineering'){
                if(isNaN(args.editingText) || args.editingText % 1 !== 0){
                    args.sheet.setValue(args.row, args.col, dbController.currentEditData ? dbController.currentEditData : '');
                    alert('工程专业只能输入整数！');
                    return;
                }
            }
            node.data[field] = args.editingText;
            sheetBillsDatas.datasIdx['rowIdx'+ args.row][field] = args.editingText;
            billsAjax.updateBills(userAccount, billsLibId, updateId, field, args.editingText);
        }
        else {
            args.sheet.getCell(args.row, args.col, GC.Spread.Sheets.SheetArea.viewport).value('');
        }
    },
    onEnterCell: function (sender, args) {
        args.sheet.repaint();
    },
    editData: function(controller){
        controller.sheet.bind(GC.Spread.Sheets.Events.EditStarting, this.onEditStart);
        controller.sheet.bind(GC.Spread.Sheets.Events.EditEnded, this.onEditEnded);
        controller.sheet.bind(GC.Spread.Sheets.Events.EnterCell, this.onEnterCell);
    }
};

var createObj = {
    newJob: function(data){
        var Job = function(data){
            this.data = data;
            //count = 0则没有被引用了
            this.count = 0;
        };
        return new Job(data);
    },
    newJobs: function(){
        var TotalJobs = function(){
            this.jobs = {};
            this.jobsArr = [];
            this.prefix = '_id';
        };

        TotalJobs.prototype.findJob = function(id){
            return this.jobs[this.prefix + id] ? this.jobs[this.prefix + id] : null;
        }


        TotalJobs.prototype.loadJobs = function (nodes, datas){
            var me = this;
            datas.forEach(function(jobData){
                var job = createObj.newJob(jobData);
                me.jobs[me.prefix + jobData.id] = job;
                me.jobsArr.push(job);
            });
            if(nodes){
                nodes.forEach(function(node){
                    node.jobs = new Array();
                    let spliceArr = [];
                    node.data.jobs.forEach(function(obj){
                        if(me.jobs[me.prefix + obj.id]){
                            node.jobs.push({job: me.jobs[me.prefix + obj.id], serialNo: obj.serialNo});
                            me.jobs[me.prefix + obj.id].count ++;
                        }
                        else {
                            spliceArr.push(obj);
                        }
                    });
                    for(let sItem of spliceArr){
                        node.data.jobs.splice(node.data.jobs.indexOf(sItem), 1);
                    }
                });
            }
        };

        TotalJobs.prototype.getUpdateIds = function(nodes, repeatId){
            var ids = [];
            nodes.forEach(function(node){
                node.jobs.forEach(function(job){
                    if(job.data.id === repeatId){
                        ids.push(node.getID());
                    }
                });
            });
            return ids;
        };

        return new TotalJobs();
    },

    newItem: function(data){
        var Item = function(data){
            this.data = data;
            this.count = 0;
        };
        return new Item(data);
    },

    newItems: function(){
        var TotalItems = function(){
            this.items = {};
            this.itemsArr = [];
            this.prefix = '_id';
        };

        TotalItems.prototype.findItem = function(id){
            return this.items[this.prefix + id] ? this.items[this.prefix + id] : null;
        };

        TotalItems.prototype.loadItems = function (nodes, datas){
            var me = this;
            datas.forEach(function(itemData){
                var item = createObj.newItem(itemData);
                me.items[me.prefix + itemData.id] = item;
                me.itemsArr.push(item);
            });
            if(nodes){
                nodes.forEach(function(node){
                    node.items = new Array();
                    let spliceArr = [];
                    node.data.items.forEach(function(obj){
                        if(me.items[me.prefix + obj.id]){
                            node.items.push({item: me.items[me.prefix + obj.id], serialNo: obj.serialNo});
                            me.items[me.prefix + obj.id].count ++;
                        }
                        else {
                            spliceArr.push(obj);
                        }
                    });
                    for(let sItem of spliceArr){
                        node.data.items.splice(node.data.items.indexOf(sItem), 1);
                    }
                });
            }
        };

        TotalItems.prototype.getUpdateIds = function(nodes, repeatId){
            var ids = [];
            nodes.forEach(function(node){
                node.items.forEach(function(item){
                    if(item.data.id === repeatId){
                        ids.push(node.getID());
                    }
                });
            });
            return ids;
        };
        return new TotalItems();
    }
};

var tools = {
    alertOpr: function(args, sheet, txt, arr, field){
        $('#alertTxt').text(txt);
        $('#alertBtn').click();
        sheet.options.isProtected = true;
        let dataCode = args.col === 0 ? 'code' : 'content';
        let orgCode =  args.row < arr.length ? arr[args.row][field].data[dataCode] : '';
        $('#alertCof').unbind('click');
        $('#alertCls').unbind('click');
        $('#alertCls').click(function () {
            sheet.options.isProtected = false;
            sheet.getCell(args.row, args.col).value(orgCode);
        });
        $('#alertCof').click(function () {
            sheet.options.isProtected = false;
            sheet.getCell(args.row, args.col).value(orgCode);
        });
    },
    alertTotalOpr: function (args, txt, arr) {
        $('#alertTxt').text(txt);
        $('#alertBtn').click();
        args.sheet.options.isProtected = true;
        let dataCode =  args.col === 0 ? 'code' : 'content';
        let orgCode =  args.row < arr.length ? arr[args.row].data[dataCode] : '';
        $('#alertCof').unbind('click');
        $('#alertCls').unbind('click');
        $('#alertCls').click(function () {
            args.sheet.options.isProtected = false;
            args.sheet.getCell(args.row, args.col).value(orgCode);
        });
        $('#alertCof').click(function () {
            args.sheet.options.isProtected = false;
            args.sheet.getCell(args.row, args.col).value(orgCode);
        });
    },
    //ref sheet up&down Move
    canUpMove: function (selected, arr) {
        return selected && arr.indexOf(selected) > 0 && arr.indexOf(selected) !== -1 ? true: false;
    },
    canDownMove: function (selected, arr) {
        return selected && arr.indexOf(selected) < arr.length -1 && arr.indexOf(selected) !== -1 ? true: false;
    },
    btnClose: function (btn) {
        btn.css("opacity", "0.2");
        btn.addClass("disabled");
        //btn.attr(attr, 'true');
    },
    btnAction: function (btn) {
        btn.css("opacity", "");
        btn.removeClass("disabled");
        //btn.attr(attr, 'false');
    },
    /*isExist: function (totalArr, field, newData, orgData){
        var isExist = false;
        if(totalArr.length > 0){
            totalArr.forEach(function(item){
                if(item.data[field] == newData && newData !== orgData){
                    isExist = true;
                }
            });
        }
        return isExist;
    },*/
    isExist: function (totalArr, field, newData){
        var isExist = false;
        if(totalArr.length > 0){
            totalArr.forEach(function(item){
                if(item.data[field] == newData){
                    isExist = true;
                }
            });
        }
        return isExist;
    },
    isRepeat: function(arr, field, newData, ref, classify){
        var isRepeat = false;
            if(classify){
                if(arr){
                    arr.forEach(function(item){
                        if(ref === 'reference' && item[classify].data[field] == newData){
                            isRepeat = true;
                        }
                        else if(ref === 'document' && item[field] == newData){
                            isRepeat = true;
                        }
                    });
                }
            }
            else {
                if(arr){
                    arr.forEach(function(item){
                        if(ref === 'reference' && item.data[field] == newData){
                            isRepeat = true;
                        }
                        else if(ref === 'document' && item[field] == newData){
                            isRepeat = true;
                        }
                    });
                }
            }
        return isRepeat;
    },

    getContentByCode: function (items, code) {
        for(let item of items){
            if(item.data.code == code){
                return item.data.content;
            }
        }
        return null;
    },

    addAttr: function(attr){
        if(!attr){
            attr = new Array();
        }
    },

    isEmptyObj: function(obj){
        let t;
        for(t in obj)
             return !1;
        return !0;
    },

    reSetCell: function(sheet, rowIdx, colIdx, value, id){
        if(value && colIdx!== null){
            sheet.getCell(rowIdx, colIdx, GC.Spread.Sheets.SheetArea.viewport).value(value);
        }
        sheet.setTag(rowIdx, 0, id);
        sheet.setTag(rowIdx, 1, id);
    },

    getIndex: function(arr, id, classify){
        var index;
        arr.forEach(function(item){
            if(item[classify].data.id === id){
                index = arr.indexOf(item);
            }
        });
        return index;
    },

    getObj: function(arr, id, classify){
        for(let i=0; i<arr.length; i++){
            if(arr[i][classify].data.id === id){
                return arr[i];
            }
        }
        return null;
    },

    getNewCode: function(totalObj, classify){
        let arr;
        if(classify === 'jobs'){
            arr = totalObj.jobsArr;
        }
        else {
            arr = totalObj.itemsArr;
        }
        tools.resort(arr, 'code', false);
        return arr.length > 0 ? arr[arr.length - 1].data.code : 0;

    },

    getValidDatas: function(sheet, setting, args){
        let validDatas = [];
        let orgRow = args.cellRange.row, orgCol = args.cellRange.col, rowCount = args.cellRange.rowCount, colCount = args.cellRange.colCount;
        let maxRow = orgRow + rowCount - 1, maxCol = orgCol + colCount -1;
        for(let i =orgRow; i<=maxRow; i++){
            let validData = {};
            for(let j= orgCol; j<=maxCol; j++){
                let value = sheet.getValue(i, j);
                if(value){
                    if(setting.cols[j].data.field === 'engineering'){
                        if(!isNaN(value) && value % 1 === 0){
                            validData[setting.cols[j].data.field] = value;
                        }
                    } else if (setting.cols[j].data.field === 'fixedFlag') {
                        let findData = BillsFixedFlagList.find((x) => x.name === value);
                        if (findData) {
                            validData[setting.cols[j].data.field] = value;
                        }
                    } else {
                        validData[setting.cols[j].data.field] = value;
                    }
                }
            }
            if(!tools.isEmptyObj(validData)){
                validDatas.push(validData);
            }
        }
        return validDatas;
    },

    getValidRow: function(sheet, rowIdx){
        const colCount = 5;
        let isValid = false;
        for(let i=0; i< colCount; i++){
            if(sheet.getValue(rowIdx, i, GC.Spread.Sheets.SheetArea.viewport)){
                isValid = true;
            }
        }
        return isValid;
    },

    getDelDatas: function(controller, totalJobs, totalItems){
        let delJobs = controller.tree.selected.jobs,
            delItems = controller.tree.selected.items,
            delJobsIds = [], delItemsIds = [];
        if(delJobs.length > 0){
            delJobs.forEach()
        }
    },

    delteSheets: function(controller, totalJobs, totalItems, jobsSheet, itemsSheet){
        var delJobs = controller.tree.selected.jobs;
        var delItems = controller.tree.selected.items;
        var delJobsIds = [];
        var delItemsIds = [];
        if(delJobs.length > 0){
            delJobs.forEach(function(obj){
                obj.job.count --;
                if(obj.job.count <=0){
                    totalJobs.jobsArr.splice(totalJobs.jobsArr.indexOf(obj), 1);
                    delJobsIds.push(obj.job.data.id)
                }
            });
            jobsAjax.deleteJobContent(userAccount, billsLibId, delJobsIds);
            tools.clearData(jobsSheet);
            tools.orderReshowData(jobsSheet, controller.tree.selected.jobs, jobsSetting, 'job', true);
        }
        if(delItems.length > 0){
            delItems.forEach(function(obj){
                obj.item.count --;
                if(obj.item.count <=0){
                    totalItems.itemsArr.splice(totalItems.itemsArr.indexOf(obj), 1);
                    delItemsIds.push(obj.item.data.id)
                }
            });
            itemsAjax.deleteItemCharacter(userAccount, billsLibId, delItemsIds);
            tools.clearData(itemsSheet);
            tools.orderReshowData(itemsSheet, controller.tree.selected.items, itemsSetting, 'item', true);
        }
        controller.delete();

    },

    deleteELes: function (arr, delIds, classifyStr){
        var ids = [];
        delIds.forEach(function(delId){
            arr.forEach(function(ele){
                if(ele[classifyStr].data.id === delId){
                    arr.splice(arr.indexOf(ele), 1);
                    ele.count--;
                    /*if(ele.count <= 0){
                        ids.push(ele.data.id);
                    }*/
                }
            });
        });
       /* if(callback){
            callback(ids);
        }*/

    },

    getSerialNo: function(arr){
        if(arr.length > 0){
            tools.resortSerialNo(arr);
            return arr[arr.length - 1].serialNo + 1;
        }
        return 1;
    },

    resortSerialNo: function(arr){
        function compare(){
            return function (a, b){
                let valA = a.serialNo,
                    valB = b.serialNo;
                return valA - valB;
            }
        }
        arr.sort(compare());
    },

    resort: function(arr, attr, isValue){
       function compare(attr){
           return function (a, b){
               var valA, valB;
               if(isValue){
                   valA = a[attr];
                   valB = a[attr];
               }
               else {
                   valA = a.data[attr];
                   valB = b.data[attr];
               }
               return valA - valB;
           }
       }
       arr.sort(compare(attr));
    },
    //update--
    orderReshowData: function(sheet, arr, setting, classify, isResort){
        sheet.setColumnCount(2, GC.Spread.Sheets.SheetArea.viewport);
        sheet.setColumnCount(2, GC.Spread.Sheets.SheetArea.colHeader);
        tools.clearData(sheet);
        if(arr.length > 0){
            sheet.suspendPaint();
            setSheet.setMaxRowCount(sheet, arr);
            if(isResort){
                tools.resortSerialNo(arr);
            }
            let length = arr.length;
            for(let i=0; i<length; i++){
                setting.cols.forEach(function(col, colIdx){
                    sheet.setTag(i, colIdx, arr[i][classify].data.id);
                    if(arr[i][classify].data[col.data.field]){
                        sheet.getCell(i, colIdx).value(arr[i][classify].data[col.data.field]);
                    }
                    else {
                        sheet.getCell(i, colIdx).value('');
                    }
                });
            }
            sheet.resumePaint();
        }
    },

    reshowData: function(sheet, arr, setting, isResort){
        sheet.suspendPaint();
        sheet.setColumnCount(2, GC.Spread.Sheets.SheetArea.viewport);
        sheet.setColumnCount(2, GC.Spread.Sheets.SheetArea.colHeader);
        tools.clearData(sheet);
        if(isResort){
            tools.resort(arr, 'code', false);
        }
        if(arr.length > 0){
            var length = arr.length;
            for(var i=0; i<length; i++){
                setting.cols.forEach(function(col, colIdx){
                    sheet.setTag(i, colIdx, arr[i].data.id);
                    if(arr[i].data[col.data.field]){
                        sheet.getCell(i, colIdx).value(arr[i].data[col.data.field]);
                    }
                    else {
                        sheet.getCell(i, colIdx).value('');
                    }
                });
            }
        }
        sheet.resumePaint();
    },

    reshowValue: function(sheet, arr, setting, isResort){
        sheet.suspendPaint();
        tools.clearData(sheet);
        sheet.setColumnCount(2, GC.Spread.Sheets.SheetArea.viewport);
        sheet.setColumnCount(2, GC.Spread.Sheets.SheetArea.colHeader);
        if(isResort){
            //tools.resort(arr, 'code', true);
            function myCompareCode(a, b){
                let valA = a.code,
                    valB = b.code;
                return valA- valB;
            }
            arr.sort(myCompareCode);
        }
        if(arr.length > 0){
            var length = arr.length;
            for(var i=0; i<length; i++){
                setting.cols.forEach(function(col, colIdx){
                    sheet.setTag(i, colIdx, arr[i].code);
                    if(arr[i][col.data.field]){
                        sheet.getCell(i, colIdx).value(arr[i][col.data.field]);
                    }
                    else {
                        sheet.getCell(i, colIdx).value('');
                    }
                });
            }
        }
        sheet.resumePaint();
    },

    clearData: function(sheet){
        sheet.clear(0, 0, sheet.getRowCount(), sheet.getColumnCount(), GC.Spread.Sheets.SheetArea.viewport,GC.Spread.Sheets.StorageType.data);
        sheet.clear(0, 0, sheet.getRowCount(), sheet.getColumnCount(), GC.Spread.Sheets.SheetArea.viewport,GC.Spread.Sheets.StorageType.tag);
    },

    getRoot: function(node){
        return node.parent ? tools.getRoot(node.parent) : node;
    },

    getBillsIds: function(callback){
        billsAjax.getBills(billsLibId, function(datas){
            var ids = [];
            datas.forEach(function(data){
                ids.push(data.ID);
            });
            if(callback){
                callback(ids);
            }
        });
    },

    delIds: function(sheet){
        var ids = [];
        var sels = sheet.getSelections();
        sels.forEach(function(sel){
            var orgRow = sel.row, rowCount = sel.rowCount, colCount = sel.colCount;
            var orgCol = sel.col === -1 ? 0 : sel.col;
            var maxRow = orgRow + rowCount - 1;
            for(var i=orgRow; i<= maxRow; i++){
                if(sheet.getTag(i, orgCol)){
                    ids.push(sheet.getTag(i, orgCol));
                }
            }
        });
        return ids;
    },

    redirect: function(billsLibId, newHref){
        mainAjax.getABillsLib(billsLibId, function(result){
            if(result.length === 0){
                window.location.href = newHref;
            }
        });
    },

    uniqArr: function (arr) {
        let newArr = [];
        for(let i=0; i<arr.length; i++){
            if(newArr.indexOf(arr[i]) === -1){
                newArr.push(arr[i]);
            }
        }
        return newArr;
    },

    uniqObjArr: function(arr){
        let uniqArr = [];
        for(let i =0; i< arr.length; i++){
            let uniqLen = uniqArr.length;
            let flag = false;
            if(uniqLen > 0){
                for(let j=0; j< uniqLen; j++){
                    if(arr[i].field === uniqArr[j].field && arr[i].data === uniqArr[j].data){
                        flag = true;
                        //uniqArr.push(arr[i]);
                    }
                }
                if(!flag){
                    uniqArr.push(arr[i]);
                }
            }
            else {
                uniqArr.push(arr[i])
            }
        }
        return uniqArr;
    },

    resetRowIdx: function(arr, beginRow){
        let rowIdx = beginRow;
        for(let i=0; i< arr.length; i++){
            if(arr[i].rowIdx !== rowIdx){
                rowIdx++;
                arr[i].rowIdx = rowIdx;
            }
        }
    },

    getsheetDatas: function(sheet, classify, controller){
        let rowCount = sheet.getRowCount();
        const colIdx = 1;
        let sheetDatas;
        if(classify === 'total'){
            sheetDatas = [];
            for(let i=0; i<rowCount; i++){
                for(let j=0; j<= 1; j++){
                    let data = sheet.getCell(i, j).value, id = sheet.getTag(i, j);
                    if(data && id){
                        let unitData ={
                            rowIdx: i,
                            colIdx: j,
                            data: data,
                            id: id
                        };
                        sheetDatas.push(unitData);
                    }
                }
            }
        }
        else if(classify === 'bills'){
            sheetDatas = {datasIdx: {},  datas: []};
            for(let i= 0; i< controller.tree.items.length; i++){
                let code = sheet.getValue(i, 0), name = sheet.getValue(i, 1),
                    unit = sheet.getValue(i, 2), ruleText = sheet.getValue(i, 3),
                    engineering = sheet.getValue(i, 4),
                    fixedFlag = sheet.getValue(i, 5);
                let data = {code: code, name: name, unit: unit, ruleText: ruleText, engineering: engineering, fixedFlag: fixedFlag, rowIdx: i};
                sheetDatas.datas.push(data);
                sheetDatas.datasIdx['rowIdx' + i] = data;
            }
        }
        else{
            sheetDatas = [];
            for(let i=0; i<rowCount; i++){
                let data = sheet.getCell(i, colIdx).value(), id = sheet.getTag(i, colIdx);
                if(data && id){
                    let rowData = {
                        rowIdx: i,
                        data: data,
                        id: id
                    }
                    sheetDatas.push(rowData);
                }
            }
        }
        return sheetDatas;
    },

    encapData: function(uncrossedDatas, crossedDatas, controller, totalJobs){
        const UpdateExist = 'updateExist', UpdateNew = 'updateNew', CreateExist = 'createExist', CreateNew = 'createNew';
        let updateDatas = [];
        let createDatas = [];
        let nodeId = controller.tree.selected.getID();
        uncrossedDatas.forEach(obj => {
            let cnDataObj, ceDataObj, content, jobId;
            let isExisit = tools.isExist(totalJobs.jobsArr, 'content', obj.data, null);
            let isRepeat = tools.isRepeat(controller.tree.selected.jobs, 'content', obj.data, 'reference', 'job');
            if(isExisit && !isRepeat){
                totalJobs.jobsArr.forEach(job => {
                   if(obj.data == job.data.content){
                       jobId = job.data.id;
                   }
                });
                ceDataObj= {
                    newData: obj.data,
                    billsLibId: billsLibId,
                    nodeId: nodeId,
                    jobId: jobId,
                    serialNo: obj.serialNo,
                    type: CreateExist
                };
                createDatas.push(ceDataObj);
            }
            if(!isExisit){
                maxJobsNumber++;
                //currentCountId++;
                cnDataObj = {
                    //id: maxJobsNumber,
                    billsLibId: billsLibId,
                    nodeId: nodeId,
                    newData: obj.data,
                    code: maxJobsNumber,
                    serialNo: obj.serialNo,
                    type: CreateNew
                };
                createDatas.push(cnDataObj);
            }
        });
        crossedDatas.forEach(cData => {
            let ueObj, unObj,  newJobId;
            let isExisit = tools.isExist(totalJobs.jobsArr, 'content', cData.newData, null);
            let isRepeat = tools.isRepeat(controller.tree.selected.jobs, 'content', cData.newData, 'reference', 'job');
            if(isExisit && !isRepeat){
                totalJobs.jobsArr.forEach(job => {
                   if(cData.newData == job.data.content){
                       newJobId = job.data.id;
                   }
                });
                ueObj = {
                    newData: cData.newData,
                    billsLibId: billsLibId,
                    nodeId: nodeId,
                    newJobId: newJobId,
                    orgJobId: cData.orgId,
                    serialNo:cData.serialNo,
                    type: UpdateExist
                };
                updateDatas.push(ueObj);
            }
            if(!isExisit && !isRepeat){
                maxJobsNumber++;
                //currentCountId++;
                unObj = {
                    //newJobId: maxJobsNumber,
                    billsLibId: billsLibId,
                    nodeId: nodeId,
                    newData: cData.newData,
                    orgJobId: cData.orgId,
                    code: maxJobsNumber,
                    serialNo: cData.serialNo,
                    type: UpdateNew
                };
                updateDatas.push(unObj);
            }
        });
        let pasteDatas = {
            updateDatas: updateDatas,
            createDatas: createDatas
        };
        return pasteDatas;
    },
    encapItemsData: function(uncrossedDatas, crossedDatas, controller, totalItems){
        const UpdateExist = 'updateExist', UpdateNew = 'updateNew', CreateExist = 'createExist', CreateNew = 'createNew';
        let updateDatas = [];
        let createDatas = [];
        let nodeId = controller.tree.selected.getID();
        uncrossedDatas.forEach(obj => {
            let cnDataObj, ceDataObj, content,itemId;
            let isExisit = tools.isExist(totalItems.itemsArr, 'content', obj.data, null);
            let isRepeat = tools.isRepeat(controller.tree.selected.items, 'content', obj.data, 'reference', 'item');
            if(isExisit && !isRepeat){
                totalItems.itemsArr.forEach(item => {
                    if(obj.data == item.data.content){
                        itemId = item.data.id;
                    }
                });
                ceDataObj= {
                    newData: obj.data,
                    billsLibId: billsLibId,
                    nodeId: nodeId,
                    itemId: itemId,
                    serialNo: obj.serialNo,
                    type: CreateExist
                };
                createDatas.push(ceDataObj);
            }
            if(!isExisit){
                maxItemsNumber++;
                //currentCountId++;
                cnDataObj = {
                   // id: maxItemsNumber,
                    billsLibId: billsLibId,
                    nodeId: nodeId,
                    newData: obj.data,
                    serialNo: obj.serialNo,
                    code: maxItemsNumber,
                    type: CreateNew
                };
                createDatas.push(cnDataObj);
            }
        });

        crossedDatas.forEach(cData => {
            let ueObj, unObj,  newItemId;
            let isExisit = tools.isExist(totalItems.itemsArr, 'content', cData.newData, null);
            let isRepeat = tools.isRepeat(controller.tree.selected.items, 'content', cData.newData, 'reference', 'item');
            if(isExisit && !isRepeat){
                totalItems.itemsArr.forEach(item => {
                    if(cData.newData == item.data.content){
                        newItemId = item.data.id;
                    }
                });
                ueObj = {
                    newData: cData.newData,
                    billsLibId: billsLibId,
                    nodeId: nodeId,
                    newItemId: newItemId,
                    orgItemId: cData.orgId,
                    serialNo: cData.serialNo,
                    type: UpdateExist
                };
                updateDatas.push(ueObj);
            }
            if(!isExisit && !isRepeat){
                maxItemsNumber++;
                //currentCountId++;
                unObj = {
                   // newItemId: maxItemsNumber,
                    billsLibId: billsLibId,
                    nodeId: nodeId,
                    newData: cData.newData,
                    orgItemId: cData.orgId,
                    code: maxItemsNumber,
                    serialNo: cData.serialNo,
                    type: UpdateNew
                };
                updateDatas.push(unObj);
            }
        });
        let pasteDatas = {
            updateDatas: updateDatas,
            createDatas: createDatas
        };
        return pasteDatas;
    },

    encapTotalJobsDatas: function(sheet, totalJobs, uncrossedDatas, crossedDatas){
        let pasteDatas;
        let rebuildArr =[];
        if(crossedDatas.length > 0){
            for(let i=0; i< crossedDatas.length; i++){
                let field = crossedDatas[i].field, data = crossedDatas[i].data;
                let isRepeat = tools.isRepeat(totalJobs.jobsArr, field, data, 'reference');
                if(isRepeat){
                    crossedDatas.splice(i--, 1);
                }
            }
            for(let i=0; i< crossedDatas.length; i++){
                let field = crossedDatas[i].field, data = crossedDatas[i].data;
                if(crossedDatas[i].field === 'code' && typeof data !== 'number' ){
                    crossedDatas.splice(i--, 1);
                }

            }
        }
        if(uncrossedDatas.length > 0){
            for(let i=0; i< uncrossedDatas.length; i++){
                let field = uncrossedDatas[i].field;
                let isRepeat = tools.isRepeat(totalJobs.jobsArr, field, uncrossedDatas[i].data, 'reference');
                if(isRepeat){
                    uncrossedDatas.splice(i--, 1);
                }
            }
            for(let i=0; i< uncrossedDatas.length; i++){
                let field = uncrossedDatas[i].field;
                if(uncrossedDatas[i].field === 'code' && typeof uncrossedDatas[i].data !== 'number' ){
                    uncrossedDatas.splice(i--, 1);

                }
            }
            rebuildArr = tools.rebuildArr(uncrossedDatas, 'create');
            function myCompare(a, b){
                if(a.rowIdx > b.rowIdx)
                    return 1;
                if(a.rowIdx < b.rowIdx)
                    return -1;
                return 0;
            }
            function myCompareCode(a, b){
                if(a.code > b.code)
                    return -1;
                if(a.code < b.code)
                    return 1;
                return 0;
            }
            if(rebuildArr.length > 0){
                rebuildArr.sort(myCompareCode);
                if(rebuildArr[0].code){
                    maxJobsNumber = maxJobsNumber + 1 > rebuildArr[0].code ? maxJobsNumber  : rebuildArr[0].code;
                }
                rebuildArr.forEach(function(data){
                    if(data.type !== 'CreateT' && data.field === 'content' ){
                        maxJobsNumber++;
                        let code = maxJobsNumber;
                        data.code = code;
                    }
                });
            }
            //rebuildArr.sort(myCompare);
        }
        //rebuildArr.sort(myCompare);
        pasteDatas = {
            updateDatas: crossedDatas,
            createDatas: rebuildArr
        }
        return pasteDatas;
    },
    encapTotalItemsDatas: function(sheet, totalItems, uncrossedDatas, crossedDatas){
        let pasteDatas;
        let rebuildArr =[];
        if(crossedDatas.length > 0){
            for(let i=0; i< crossedDatas.length; i++){
                let field = crossedDatas[i].field, data = crossedDatas[i].data;
                let isRepeat = tools.isRepeat(totalItems.itemsArr, field, data, 'reference');
                if(isRepeat){
                    crossedDatas.splice(i--, 1);
                }
            }
            for(let i=0; i< crossedDatas.length; i++){
                let field = crossedDatas[i].field, data = crossedDatas[i].data;
                if(crossedDatas[i].field === 'code' && typeof data !== 'number' ){
                    crossedDatas.splice(i--, 1);
                }
            }
        }
        if(uncrossedDatas.length > 0){
            for(let i=0; i< uncrossedDatas.length; i++){
                let field = uncrossedDatas[i].field;
                let isRepeat = tools.isRepeat(totalItems.itemsArr, field, uncrossedDatas[i].data, 'reference');
                if(isRepeat){
                    uncrossedDatas.splice(i--, 1);
                }
            }
            for(let i=0; i< uncrossedDatas.length; i++){
                let field = uncrossedDatas[i].field;
                if(uncrossedDatas[i].field === 'code' && typeof uncrossedDatas[i].data !== 'number' ){
                    uncrossedDatas.splice(i--, 1);

                }
            }
            rebuildArr = tools.rebuildArr(uncrossedDatas, 'create');
            function myCompare(a, b){
                if(a.rowIdx > b.rowIdx)
                    return 1;
                if(a.rowIdx < b.rowIdx)
                    return -1;
                return 0;
            }
            function myCompareCode(a, b){
                if(a.code > b.code)
                    return -1;
                if(a.code < b.code)
                    return 1;
                return 0;
            }
            //rebuildArr.sort(myCompare);
            if(rebuildArr.length > 0){
                rebuildArr.sort(myCompareCode);
                if(rebuildArr[0].code){
                    maxItemsNumber = maxItemsNumber + 1 > rebuildArr[0].code ? maxItemsNumber  : rebuildArr[0].code;
                }
                rebuildArr.forEach(function(data){
                    if(data.type !== 'CreateT' && data.field === 'content' ){
                        maxItemsNumber ++;
                        let code = maxItemsNumber;
                        data.code = code;
                    }
                });
            }
        }
       // rebuildArr.sort(myCompare);
        pasteDatas = {
            updateDatas: crossedDatas,
            createDatas: rebuildArr
        }
        return pasteDatas;
    },
    encapValues: function(sheet, totalItems, uncrossedDatas, crossedDatas){
        let rebuildArr =[];
        let rebuildUpdateDatas = [];
        let valuesArr = valueController.getValues(totalItems, selectedId);
        function myCompare(a, b){
            if(a.rowIdx > b.rowIdx)
                return 1;
            if(a.rowIdx < b.rowIdx)
                return -1;
            return 0;
        }
        if(crossedDatas.length > 0){
            for(let i=0; i< crossedDatas.length; i++){
                let field = crossedDatas[i].field, data = crossedDatas[i].data;
                let isRepeat = tools.isRepeat(valuesArr, field, data, 'document', 'value');
                if(isRepeat){
                    crossedDatas.splice(i--, 1);
                }
            }
            for(let i=0; i< crossedDatas.length; i++){
                let field = crossedDatas[i].field, data = crossedDatas[i].data;
                if(crossedDatas[i].field === 'code' && typeof data !== 'number' ){
                    crossedDatas.splice(i--, 1);
                }
            }
            rebuildUpdateDatas = tools.rebuildArr(crossedDatas, 'update');
            rebuildUpdateDatas.sort(myCompare);
            for(let i =0; i< rebuildUpdateDatas.length; i++){
                rebuildUpdateDatas[i].itemId = selectedId;
            }
        }
        if(uncrossedDatas.length > 0){
            for(let i=0; i< uncrossedDatas.length; i++){
                let field = uncrossedDatas[i].field;
                let isRepeat = tools.isRepeat(valuesArr, field, uncrossedDatas[i].data, 'document', 'value');
                if(isRepeat){
                    uncrossedDatas.splice(i--, 1);
                }
            }
            for(let i=0; i< uncrossedDatas.length; i++){
                let field = uncrossedDatas[i].field;
                if(uncrossedDatas[i].field === 'code' && typeof uncrossedDatas[i].data !== 'number' ){
                    uncrossedDatas.splice(i--, 1);
                }
            }
            rebuildArr = tools.rebuildArr(uncrossedDatas, 'create');
            //rebuildArr.sort(myCompare);
            function myCompareCode(a, b){
                let valA = a.code,
                    valB = b.code;
                return valB- valA;
            }
            rebuildArr.sort(myCompareCode);
            let newCode = valueController.getCode(totalItems, selectedId);
            if(rebuildArr[0].code){
                newCode = newCode > rebuildArr[0].code ? newCode : rebuildArr[0].code + 1;
            }
            for(let i=0; i< rebuildArr.length; i++){
                rebuildArr[i].itemId = selectedId;
                if(rebuildArr[i].type !== 'CreateT' && rebuildArr[i].field === 'value'){
                    rebuildArr[i].code = newCode;
                    newCode++;
                }
            }
        }
        //backendOP
        let pasteDatas = {
            updateDatas: rebuildUpdateDatas,
            createDatas: rebuildArr
        };
        return pasteDatas;
    },

    rebuildArr: function(arr, classify){
        let conformDatas = [];
        let flag = true;
        for(let i=0; i< arr.length; i++){
            for(let j=i+1; j<arr.length; j++){
                if(arr[i].rowIdx === arr[j].rowIdx){
                    flag = false;
                    let field = arr[i].field;
                    let conformData;
                    if(classify === 'create'){
                        if(field === 'code'){
                            conformData = {
                                billsLibId: billsLibId,
                                code: arr[i].data,
                                content: arr[j].data,
                                rowIdx: arr[i].rowIdx,
                                type: 'CreateT'
                            }
                        }
                        else {
                            conformData = {
                                billsLIbId: billsLibId,
                                code: arr[j].data,
                                content: arr[i].data,
                                rowIdx: arr[i].rowIdx,
                                type: 'CreateT'
                            }
                        }
                    }
                    else {
                        if(field === 'code'){
                            conformData = {
                                billsLibId: billsLibId,
                                code: arr[i].data,
                                content: arr[j].data,
                                rowIdx: arr[i].rowIdx,
                                orgId: arr[i].orgId,
                                type: 'UpdateT'
                            }
                        }
                        else {
                            conformData = {
                                billsLIbId: billsLibId,
                                code: arr[j].data,
                                content: arr[i].data,
                                rowIdx: arr[i].rowIdx,
                                orgId: arr[i].orgId,
                                type: 'UpdateT'
                            }
                        }
                    }
                    conformDatas.push(conformData);
                }
            }

        }
        for(let i =0; i< arr.length; i++){
            let flag = true;
            for(let j=0; j<arr.length; j++){
                if(arr[i].rowIdx === arr[j].rowIdx && arr[i].field !== arr[j].field){
                    flag = false;
                }
            }
            if(flag){

                conformDatas.push(arr[i]);
            }
        }
        return conformDatas;
    },

    isDef: function (v) {
        return v !== undefined && v !== null;
    },
    //返回
    sectionInfoNull: function (sectionInfo) {
        for(let info in sectionInfo){
            if(!this.isDef(sectionInfo[info])){
                return info;
            }
        }
        return false;
    },

    getSectionInfo: function (node) {
        let parentIDs = [];
        let sectionInfo = {first: null, second: null, third: null};
        getParent(node);
        if(this.isDef(parentIDs[parentIDs.length - 1])){
            sectionInfo.first = parentIDs[parentIDs.length - 1];
        }
        if(this.isDef(parentIDs[parentIDs.length - 2])){
            sectionInfo.second = parentIDs[parentIDs.length - 2];
        }
        if(this.isDef(parentIDs[parentIDs.length - 3])){
            sectionInfo.third = parentIDs[parentIDs.length - 3];
        }
        return sectionInfo;
        function getParent(node){
            if(node.parent){
                parentIDs.push(node.parent.data.ID);
                getParent(node.parent);
            }
        }
    },

    getUpdateSectionData: function (nodes) {
        let rst = [];
        for(let node of nodes){
            rst.push({ID: node.getID(), sectionInfo: tools.getSectionInfo(node)});
        }
        return rst;
    },

    //获取节点底下所有子节点
    getChildrenNodes: function (nodes) {
        let rst = [];
        for(let node of nodes){
            getChild(node.children);
        }
        function getChild(ns){
            rst = rst.concat(ns);
            for(let n of ns){
                if(n.children.length > 0){
                    getChild(n.children);
                }
            }
        }
        return rst;
    },

    getSameDepthNodes: function(controller){
        const items = controller.tree.items;
        let rst = [];
        let sel = controller.sheet.getSelections()[0];
        let selectedDepth = controller.tree.selected.depth();
        for(let i = 0; i < sel.rowCount; i++){
            let row = sel.row + i;
            if(items[row].depth() === selectedDepth){
                rst.push(items[row]);
            }
        }
        return rst;
    }
};

let pasteController = {
    frontOperator: function(sheet, setting, controller, totalJobs, datas){
        const UpdateExist = 'updateExist', UpdateNew = 'updateNew', CreateExist = 'createExist', CreateNew = 'createNew';
        if(datas.length > 0){
            for(let i=0; i<datas.length; i++){
                if(datas[i]){
                    if(datas[i].type === UpdateExist){
                        totalJobs.jobsArr.forEach(job => {
                            if(job.data.content == datas[i].newData){
                                let serialNo = datas[i].serialNo;
                                let index = tools.getIndex(controller.tree.selected.jobs, datas[i].orgJobId, 'job');
                                job.count ++;
                                controller.tree.selected.jobs.splice(index, 1);
                                controller.tree.selected.jobs.splice(index, 0, {job: job, serialNo: serialNo});
                            }
                        });
                    }
                   else if(datas[i].type === UpdateNew){
                        let newJobData, newJob;
                        let newJobId = datas[i].newJobId, serialNo = datas[i].serialNo;
                        newJobData = {id: newJobId, content: datas[i].newData, code: datas[i].code};
                        newJob = createObj.newJob(newJobData);
                        newJob.count = 1;
                        totalJobs.jobs[totalJobs.prefix + newJobId] = newJob;
                        totalJobs.jobsArr.push(newJob);
                        var index = tools.getIndex(controller.tree.selected.jobs, datas[i].orgJobId, 'job');
                        controller.tree.selected.jobs.splice(index, 1);
                        controller.tree.selected.jobs.splice(index, 0, {job: newJob, serialNo: serialNo});
                    }
                   else if(datas[i].type === CreateExist){
                        let serialNo = datas[i].serialNo;
                        totalJobs.jobsArr.forEach(job => {
                            if(job.data.content == datas[i].newData){
                                job.count ++;
                                controller.tree.selected.jobs.push({job: job, serialNo: serialNo});
                            }

                        });
                    }
                   else if(datas[i].type === CreateNew){
                        let newJobId = datas[i].newJobId, serialNo = datas[i].serialNo;
                        let newJobData, newJob;
                        newJobData = {id: newJobId, content: datas[i].newData, code: datas[i].code};
                        newJob = createObj.newJob(newJobData);
                        newJob.count = 1;
                        totalJobs.jobs[totalJobs.prefix + newJobId] = newJob;
                        totalJobs.jobsArr.push(newJob);
                        controller.tree.selected.jobs.push({job: newJob, serialNo: serialNo});
                    }
                }
            }
        }
        //resort&reshow
        tools.orderReshowData(sheet, controller.tree.selected.jobs, setting, 'job', true);
        sheetDatas = tools.getsheetDatas(sheet);

    },
    frontItemsRelOperator: function(sheet, setting, controller, totalItems, datas){
        const UpdateExist = 'updateExist', UpdateNew = 'updateNew', CreateExist = 'createExist', CreateNew = 'createNew';
        if(datas.length > 0){
            for(let i =0; i<datas.length; i++){
                if(datas[i]){
                    if(datas[i].type == UpdateExist){
                        let serialNo = datas[i].serialNo;
                        totalItems.itemsArr.forEach(item => {
                            if(item.data.content === datas[i].newData){
                                let index = tools.getIndex(controller.tree.selected.items, datas[i].orgItemId, 'item');
                                item.count ++;
                                controller.tree.selected.items.splice(index, 1);
                                controller.tree.selected.items.splice(index, 0, {item: item, serialNo: serialNo});
                            }
                        });
                    }
                   else if(datas[i].type === UpdateNew){
                        let newItemData, newItem;
                        let newItemId = datas[i].newItemId, serialNo = datas[i].serialNo;
                        newItemData = {id: newItemId, content: datas[i].newData, code: datas[i].code};
                        newItem = createObj.newItem(newItemData);
                        newItem.count = 1;
                        totalItems.items[totalItems.prefix + newItemId] = newItem;
                        totalItems.itemsArr.push(newItem);
                        var index = tools.getIndex(controller.tree.selected.items, datas[i].orgItemId, 'item');
                        controller.tree.selected.items.splice(index, 1);
                        controller.tree.selected.items.splice(index, 0, {item: newItem, serialNo: serialNo});
                    }
                   else if(datas[i].type === CreateExist){
                        let serialNo = datas[i].serialNo;
                        totalItems.itemsArr.forEach(item => {
                            if(item.data.content == datas[i].newData){
                                item.count ++;
                                controller.tree.selected.items.push({item: item, serialNo: serialNo});
                            }

                        });
                    }
                   else if(datas[i].type === CreateNew){
                        let newItemId = datas[i].newItemId, serialNo = datas[i].serialNo;
                        let newItemData, newItem;
                        newItemData = {id: newItemId, content: datas[i].newData, code: datas[i].code};
                        newItem = createObj.newItem(newItemData);
                        newItem.count = 1;
                        totalItems.items[totalItems.prefix + newItemId] = newItem;
                        totalItems.itemsArr.push(newItem);
                        controller.tree.selected.items.push({item: newItem, serialNo: serialNo});
                    }
                }
            }
        }
        //resort&reshow
        tools.orderReshowData(sheet, controller.tree.selected.items, setting, 'item', true);
        sheetItemsDatas = tools.getsheetDatas(sheet);

    },
    pasteJobsFront: function(sheet, totalJobs, datas){
        const Update = 'Update', CreateT = 'CreateT';
        if(datas.length > 0){
            for(let i=0; i<datas.length; i++){
                let newJobData, newJob;
                if(datas[i]){
                    if(datas[i].type === Update){
                        totalJobs.jobsArr.forEach(job => {
                            if(job.data.id === datas[i].orgId){
                                job.data[datas[i].field] = datas[i].data;
                            }
                        });
                    }
                   else if(datas[i].type === CreateT){
                        //maxJobsNumber++;
                        // maxJobsNumber = maxJobsNumber >= datas[i].code ? maxJobsNumber : datas[i].code;
                        newJobData = {id: datas[i].newJobId, content: datas[i].content, code: datas[i].code};
                        newJob = createObj.newJob(newJobData);
                        totalJobs.jobsArr.push(newJob);
                    }
                   else if(datas[i].type !== CreateT && datas[i].field === 'content'){
                        newJobData = {id: datas[i].newJobId, content: datas[i].data, code: datas[i].code};
                        newJob = createObj.newJob(newJobData);
                        totalJobs.jobsArr.push(newJob);
                    }
                   else if(datas[i].type !== 'CreateT' && datas[i].field === 'code'){
                        //  maxJobsNumber++;
                        // maxJobsNumber = maxJobsNumber >= datas[i].data  ? maxJobsNumber : datas[i].data;
                        newJobData = {id: datas[i].newJobId, content: '', code: datas[i].data};
                        newJob = createObj.newJob(newJobData);
                        totalJobs.jobsArr.push(newJob);
                    }
                }
            }
        }
        setSheet.setMaxRowCount(sheet, totalJobs.jobsArr);
        tools.reshowData(sheet, totalJobs.jobsArr, totalJobsSetting, true);
        sheetJobsDatas = tools.getsheetDatas(sheet, 'total');
    },
    pasteItemsFront: function(sheet, totalItems, datas){
        const Update = 'Update', CreateT = 'CreateT';
        if(datas.length > 0){
            for(let i=0; i<datas.length; i++){
                let newItemData, newItem;
                if(datas[i]){
                    if(datas[i].type === Update){
                        totalItems.itemsArr.forEach(item => {
                            if(item.data.id === datas[i].orgId){
                                item.data[datas[i].field] = datas[i].data;
                            }
                        });
                    }
                   else if(datas[i].type === CreateT){
                        newItemData = {id: datas[i].newItemId, content: datas[i].content, code: datas[i].code, itemValue: []};
                        newItem = createObj.newItem(newItemData);
                        totalItems.itemsArr.push(newItem);
                        totalItems.items[totalItems.prefix + datas[i].newItemId] = newItem;
                    }
                   else if(datas[i].type !== CreateT && datas[i].field === 'content'){
                        newItemData = {id: datas[i].newItemId, content: datas[i].data, code: datas[i].code, itemValue: []};
                        newItem = createObj.newItem(newItemData);
                        totalItems.itemsArr.push(newItem);
                        totalItems.items[totalItems.prefix + datas[i].newItemId] = newItem;
                    }
                   else if(datas[i].type !== 'CreateT' && datas[i].field === 'code'){
                        newItemData = {id: datas[i].newItemId, content: '', code: datas[i].data, itemValue: []};
                        newItem = createObj.newItem(newItemData);
                        totalItems.itemsArr.push(newItem);
                        totalItems.items[totalItems.prefix + datas[i].newItemId] = newItem;
                    }
                }
            }
        }
        setSheet.setMaxRowCount(sheet, totalItems.itemsArr);
        tools.reshowData(sheet, totalItems.itemsArr, totalItemsSetting, true);
        totalItemsDatas = tools.getsheetDatas(sheet, 'total');
    },

    pasteValueFront: function(sheet, totalItems, datas){
        let backendUpdateDatas = [];
        let valuesArr = valueController.getValues(totalItems, selectedId);
        if(datas.length > 0){
            for(let i =0; i< datas.length; i++){
                let index;
                if(datas[i]){
                    if(datas[i].type === 'UpdateT'){
                        if(valuesArr){
                            for(let j=0; j< valuesArr.length; j++){
                                if(datas[i].orgId === valuesArr[j].code){
                                    index = j;
                                    valuesArr.splice(j--, 1);
                                }
                            }
                            let updateEle = {code: datas[i].code, value: datas[i].content};
                            valuesArr.splice(index, 0, updateEle);
                        }
                    }
                   else if(datas[i].type === 'Update' && datas[i].field === 'code'){
                        if(valuesArr){
                            for(let j=0; j< valuesArr.length; j++){
                                if(datas[i].orgId === valuesArr[j].code){
                                    valuesArr[j].code = datas[i].data;
                                }
                            }
                        }
                    }
                   else if(datas[i].type === 'Update' && datas[i].field === 'value'){
                        if(valuesArr){
                            for(let j=0; j< valuesArr.length; j++){
                                if(datas[i].orgId === valuesArr[j].code){
                                    valuesArr[j].value = datas[i].data
                                }
                            }
                        }
                    }
                   else if(datas[i].type === 'CreateT'){
                        let newValueData = {value: datas[i].content, code: datas[i].code};
                        valuesArr.push(newValueData);

                    }
                   else if(datas[i].type === 'Create' && datas[i].field === 'value'){
                        let newValueData = {value: datas[i].data, code: datas[i].code};
                        valuesArr.push(newValueData);
                    }
                   else if(datas[i].type === 'Create' && datas[i].field === 'code'){
                        let newValueData = {value: '', code: datas[i].data};
                        valuesArr.push(newValueData);
                    }
                }
            }
        }
        tools.reshowValue(sheet, valuesArr, eigenValueSetting, true);
        valueDatas = tools.getsheetDatas(sheet, 'total');
    }
};

var jobsController = {
    currentEditData: null,
    totalJobs: null,
    onEditStart: function (sender, args) {
        let me = jobsController;
        me.currentEditData = args.sheet.getValue(args.row, args.col);
    },
    onEditEnded: function (sender, args) {
        let me = jobsController;
        let sheet = args.sheet;
        let controller = dbController.controller;
        let totalJobs = me.totalJobs;
        let setting = jobsSetting;
        var field, newData = args.editingText, id = sheet.getTag(args.row, args.col);
        setting.cols.forEach(function (col, idx) {
            if (args.col === idx) {
                field = col.data.field;
            }
        });
        if (controller.tree.selected && newData != me.currentEditData) {
            var isExist = tools.isExist(totalJobs.jobsArr, field, newData);
            var isRepeat = tools.isRepeat(controller.tree.selected.jobs, field ,newData, 'reference', 'job');
            //create
            if(!id && newData && !isRepeat){
                if(isExist){
                    jobsController.createExist(sheet, controller, totalJobs, field, newData, args, setting);
                }
                else {
                    jobsController.createNew(sheet, controller, totalJobs, field, newData, args, setting);
                }
            }
            //update
            else if(id && !isRepeat){
                jobsController.update(sheet, controller, totalJobs, field, newData, id, isExist, args, setting);
            }
            //处理重复
            if(isRepeat){
                tools.alertOpr(args, sheet, '该工作内容已存在！', controller.tree.selected.jobs, 'job');
            }
        }
        else {
            sheet.getCell(args.row, args.col).value(me.currentEditData ? me.currentEditData : '');
        }
    },
    editData: function(sheet){
        let me = jobsController;
        sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.onEditStart);
        sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
    },


    createNew: function(sheet, controller, totalJobs, field, newData, args, setting){
        if(field === 'content'){
            maxJobsNumber++;
            //update--
            let serialNo = tools.getSerialNo(controller.tree.selected.jobs);
            //--
            jobsAjax.edCreateJob(userAccount, billsLibId, controller.tree.selected.getID(), newData, maxJobsNumber, serialNo, function(newJobId){
                var newJobData, newJob;
                newJobData = {id: newJobId, content: newData, code: maxJobsNumber};
                newJob = createObj.newJob(newJobData);
                newJob.count = 1;
                totalJobs.jobs[totalJobs.prefix + newJobId] = newJob;
                totalJobs.jobsArr.push(newJob);
                controller.tree.selected.jobs.push({job: newJob, serialNo: serialNo});//update--
                tools.orderReshowData(sheet, controller.tree.selected.jobs, setting, 'job', true)//update--
            });
        }
        else {
            tools.alertOpr(args, sheet, '该编号不存在，请重新输入！', controller.tree.selected.jobs, 'job');
        }
    },

    createExist: function(sheet, controller, totalJobs, field, newData, args, setting){
        totalJobs.jobsArr.forEach(function(job){
            if(field === 'content'&& newData === job.data.content){
                let serialNo = tools.getSerialNo(controller.tree.selected.jobs);//update--
                //billsAjax.updateBills(billsLibId, controllers.tree.selected.getID(), 'jobs', job.data.id);//update--
                billsAjax.updateBills(userAccount, billsLibId, controller.tree.selected.getID(), 'jobs', {id: job.data.id, serialNo: serialNo});//update--
                job.count++;
               // controllers.tree.selected.jobs.push(job);//update--
                controller.tree.selected.jobs.push({job: job, serialNo: serialNo});//update--
                //tools.reshowData(sheet, controllers.tree.selected.jobs, setting, true);//update--
                tools.orderReshowData(sheet,controller.tree.selected.jobs, setting, 'job', true);
            }
            else if(field == 'code' && newData == job.data.code){
                let serialNo = tools.getSerialNo(controller.tree.selected.jobs);//update--
                billsAjax.updateBills(userAccount, billsLibId, controller.tree.selected.getID(), 'jobs', {id: job.data.id, serialNo: serialNo});//update--
                job.count++;
                controller.tree.selected.jobs.push({job: job, serialNo: serialNo});//update--
               // tools.reshowData(sheet, controllers.tree.selected.jobs, setting, true);//update--
                tools.orderReshowData(sheet, controller.tree.selected.jobs, setting, 'job', true);
            }
        });
    },
    update: function(sheet, controller, totalJobs, field, newData, id, isExist, args, setting){
        if(isExist){
            totalJobs.jobsArr.forEach(function(job){
                if(field == 'code' && job.data[field] == newData){
                    let serialNo = tools.getObj(controller.tree.selected.jobs, id, 'job').serialNo;//update--add
                    let index = tools.getIndex(controller.tree.selected.jobs, id, 'job');//update-- getIndex
                    job.count++;
                    controller.tree.selected.jobs.splice(index, 1);
                    controller.tree.selected.jobs.splice(index, 0, {job: job, serialNo: serialNo});//update--
                    billsAjax.updateBillsArr(userAccount, billsLibId, controller.tree.selected.getID(), id, job.data.id, 'update', 'jobs');
                    tools.orderReshowData(sheet, controller.tree.selected.jobs, setting, 'job', true);
                }
                if(field === 'content' && job.data[field] === newData){
                    let serialNo = tools.getObj(controller.tree.selected.jobs, id, 'job').serialNo;//update--add
                    let index = tools.getIndex(controller.tree.selected.jobs, id, 'job');
                    job.count++;
                    controller.tree.selected.jobs.splice(index, 1);
                    controller.tree.selected.jobs.splice(index, 0, {job: job, serialNo: serialNo});//update--
                    billsAjax.updateBillsArr(userAccount, billsLibId, controller.tree.selected.getID(), id, job.data.id, 'update', 'jobs');
                   // tools.reshowData(sheet, controllers.tree.selected.jobs, setting, true);//update--
                    tools.orderReshowData(sheet,controller.tree.selected.jobs, setting, 'job', true);
                }
            });
        }
        else{
            if(field === 'content'){
                maxJobsNumber++;
                //let serialNo = tools.getSerialNo(controllers.tree.selected.jobs);//update--
                let serialNo = tools.getObj(controller.tree.selected.jobs, id, 'job').serialNo;
                jobsAjax.edUpdateJob(userAccount, billsLibId, controller.tree.selected.getID(), newData, maxJobsNumber, id, function(newJobId){//update--
                    var newJobData, newJob;
                    newJobData = {id: newJobId, content: newData, code: maxJobsNumber};
                    newJob = createObj.newJob(newJobData);
                    newJob.count = 1;
                    totalJobs.jobs[totalJobs.prefix + newJobId] = newJob;
                    totalJobs.jobsArr.push(newJob);
                    var index = tools.getIndex(controller.tree.selected.jobs, id, 'job');
                    controller.tree.selected.jobs.splice(index, 1);
                    controller.tree.selected.jobs.splice(index, 0, {job: newJob, serialNo: serialNo});//update--
                    //tools.reshowData(sheet, controllers.tree.selected.jobs, setting, true);//update--
                    tools.orderReshowData(sheet, controller.tree.selected.jobs, setting, 'job', true);//update--
                });
            }
            else {
               tools.alertOpr(args, sheet, '该编号不存在，请重新输入！', controller.tree.selected.jobs, 'job');
              /*  //todo: 提示窗口
                console.log(`enter`);
                console.log(typeof newData);
                if(typeof newData === 'number'){
                    console.log(`orgJobData: ${orgJobData}`);
                    sheet.getCell(args.row, args.col).value(orgJobData);
                }
                else {
                  //编号只能是数字
                    sheet.getCell(args.row, args.col).value('');
                }*/
            }
        }
    },
    upMove: function (controller, sheet) {
        let updateSelArr = [];
        $('#upMove').attr('doing', 'true');
        tools.btnClose($('#upMove'));
        let args = controller.tree.selected.args,
            thisJob = controller.tree.selected.jobs[args.row],
            preJob = controller.tree.selected.jobs[args.row - 1],
            tempSerialNo;
        //switch serialNo
        tempSerialNo = thisJob.serialNo;
        thisJob.serialNo = preJob.serialNo;
        preJob.serialNo = tempSerialNo;
        updateSelArr.push({id: thisJob.job.data.id, serialNo: thisJob.serialNo});
        updateSelArr.push({id: preJob.job.data.id, serialNo: preJob.serialNo});
        billsAjax.updateSerialNo(billsLibId, controller.tree.selected.getID(), updateSelArr, 'jobs', function () {
            tools.orderReshowData(sheet, controller.tree.selected.jobs, jobsSetting, 'job', true);
            sheet.setActiveCell(args.row -1, args.col);
            controller.tree.selected.args.row = args.row - 1;
            $('#upMove').attr('doing', 'false');
            if(tools.canUpMove(controller.tree.selected.jobs[controller.tree.selected.args.row], controller.tree.selected.jobs)){
                $('#upMove').attr('canMove', 'true');
                tools.btnAction($('#upMove'));
            }
            else{
                $('#upMove').attr('canMove', 'false');
            }
            if(tools.canDownMove(controller.tree.selected.jobs[controller.tree.selected.args.row], controller.tree.selected.jobs)){
                $('#downMove').attr('canMove', true);
                tools.btnAction($('#downMove'));
            }
            else{
                $('#downMove').attr('canMove', 'false');
                tools.btnClose($('#downMove'));
            }
        });
    },
    downMove: function (controller, sheet) {
        let updateSelArr = [];
        $('#downMove').attr('doing', 'true');
        tools.btnClose($('#downMove'));
        let tempSerialNo = controller.tree.selected.jobs[controller.tree.selected.args.row].serialNo;
        controller.tree.selected.jobs[controller.tree.selected.args.row].serialNo = controller.tree.selected.jobs[controller.tree.selected.args.row + 1].serialNo;
        controller.tree.selected.jobs[controller.tree.selected.args.row + 1].serialNo = tempSerialNo;
        updateSelArr.push({id: controller.tree.selected.jobs[controller.tree.selected.args.row].job.data.id, serialNo: controller.tree.selected.jobs[controller.tree.selected.args.row].serialNo});
        updateSelArr.push({id: controller.tree.selected.jobs[controller.tree.selected.args.row + 1].job.data.id, serialNo: controller.tree.selected.jobs[controller.tree.selected.args.row + 1].serialNo});
        billsAjax.updateSerialNo(billsLibId, controller.tree.selected.getID(), updateSelArr, 'jobs', function () {
            tools.orderReshowData(sheet, controller.tree.selected.jobs, jobsSetting, 'job', true);
            sheet.setActiveCell(controller.tree.selected.args.row + 1, controller.tree.selected.args.col);
            controller.tree.selected.args.row = controller.tree.selected.args.row + 1;
            $('#downMove').attr('doing', 'false');
            if(tools.canDownMove(controller.tree.selected.jobs[controller.tree.selected.args.row], controller.tree.selected.jobs)){
                $('#downMove').attr('canMove', 'true');
                tools.btnAction($('#downMove'));
            }
            else{
                $('#downMove').attr('canMove', 'false');
            }
            if(tools.canUpMove(controller.tree.selected.jobs[controller.tree.selected.args.row], controller.tree.selected.jobs)){
                $('#upMove').attr('canMove', 'true');
                tools.btnAction($('#upMove'));
            }
            else{
                $('#upMove').attr('canMove', 'false');
                tools.btnClose($('#upMove'));
            }
        });
    }

};

var itemsController = {
    currentEditData: null,
    totalItems: null,
    onEditStart: function (sender, args) {
        let me = itemsController;
        me.currentEditData = args.sheet.getValue(args.row, args.col);
    },
    onEditEnded: function (sender, args) {
        let me = itemsController;
        let controller = dbController.controller;
        let totalItems = me.totalItems;
        let setting = itemsSetting;
        let sheet = args.sheet;
        var field, newData = args.editingText, id = sheet.getTag(args.row, args.col);
        setting.cols.forEach(function (col, idx) {
            if (args.col === idx) {
                field = col.data.field;
            }
        });
        if (controller.tree.selected && newData != me.currentEditData) {
            var isExist = tools.isExist(totalItems.itemsArr, field, newData);
            var isRepeat = tools.isRepeat(controller.tree.selected.items, field ,newData, 'reference', 'item');
            //create
            if(!id && newData && !isRepeat){
                if(isExist){
                    itemsController.createExist(sheet, controller, totalItems, field, newData, args, setting);
                }
                else {
                    itemsController.createNew(sheet, controller, totalItems, field, newData, args, setting);
                }
            }
            //update
            else if(id && !isRepeat){
                itemsController.update(sheet, controller, totalItems, field, newData, id, isExist, args, setting);
            }
            //处理重复
            if(isRepeat){
                tools.alertOpr(args, sheet, '该项目特征已存在！', controller.tree.selected.items, 'item');
            }
        }
        else {
            sheet.getCell(args.row, args.col).value(me.currentEditData ? me.currentEditData : '');
        }
    },
    editData: function(sheet){
        let me = itemsController;
        sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.onEditStart);
        sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
    },

    createNew: function(sheet, controller, totalItems, field, newData, args, setting){
        if(field === 'content'){
            maxItemsNumber++;
            let serialNo = tools.getSerialNo(controller.tree.selected.items);
            itemsAjax.edCreateItem(userAccount, billsLibId, controller.tree.selected.getID(), newData, maxItemsNumber, serialNo, function(newItemId){
                let newItemData, newItem;
                newItemData = {id: newItemId, content: newData, code: maxItemsNumber};
                newItem = createObj.newItem(newItemData);
                newItem.count = 1;
                totalItems.items[totalItems.prefix + newItemId] = newItem;
                totalItems.itemsArr.push(newItem);
                controller.tree.selected.items.push({item: newItem, serialNo: serialNo});
                //tools.reshowData(sheet, controllers.tree.selected.items, setting, true);
                tools.orderReshowData(sheet, controller.tree.selected.items, setting, 'item', true);
            });
        }
        else {
            tools.alertOpr(args, sheet, '该编号不存在，请重新输入！', controller.tree.selected.items, 'item');
        }
    },

    createExist: function(sheet, controller, totalItems, field, newData, args, setting){
        totalItems.itemsArr.forEach(function(item){
            if(field === 'content'&& newData === item.data.content){
                let serialNo = tools.getSerialNo(controller.tree.selected.items);
                billsAjax.updateBills(userAccount, billsLibId, controller.tree.selected.getID(), 'items', {id: item.data.id, serialNo: serialNo});
                item.count++;
                controller.tree.selected.items.push({item: item, serialNo: serialNo});
                tools.orderReshowData(sheet, controller.tree.selected.items, setting, 'item', true);
            }
            else if(field == 'code' && newData == item.data.code){
                let serialNo = tools.getSerialNo(controller.tree.selected.items);
                billsAjax.updateBills(userAccount, billsLibId, controller.tree.selected.getID(), 'items', {id: item.data.id, serialNo: serialNo});
                item.count++;
                controller.tree.selected.items.push({item: item, serialNo: serialNo});
                tools.orderReshowData(sheet, controller.tree.selected.items, setting, 'item', true);
            }
        });
    },

    update: function(sheet, controller, totalItems, field, newData, id, isExist, args, setting){
        if(isExist){
            totalItems.itemsArr.forEach(function(item){
                if(field == 'code' && item.data[field] == newData){
                    let serialNo = tools.getObj(controller.tree.selected.items, id, 'item').serialNo;
                    let index = tools.getIndex(controller.tree.selected.items, id, 'item');
                    item.count++;
                    controller.tree.selected.items.splice(index, 1);
                    controller.tree.selected.items.splice(index, 0, {item: item, serialNo: serialNo});
                    billsAjax.updateBillsArr(userAccount, billsLibId, controller.tree.selected.getID(), id, item.data.id, 'update', 'items');
                    tools.orderReshowData(sheet, controller.tree.selected.items, setting, 'item', true);
                }
                if(field === 'content' && item.data[field] === newData){
                    let serialNo = tools.getObj(controller.tree.selected.items, id, 'item').serialNo;
                    let index = tools.getIndex(controller.tree.selected.items, id, 'item');
                    item.count++;
                    controller.tree.selected.items.splice(index, 1);
                    controller.tree.selected.items.splice(index, 0, {item: item, serialNo: serialNo});
                    billsAjax.updateBillsArr(userAccount, billsLibId, controller.tree.selected.getID(), id, item.data.id, 'update', 'items');
                    tools.orderReshowData(sheet, controller.tree.selected.items, setting, 'item', true);
                }
            });
        }
        else{
            if(field === 'content'){
                maxItemsNumber++;
                let serialNo = tools.getObj(controller.tree.selected.items, id, 'item').serialNo;
                itemsAjax.edUpdateItem(userAccount, billsLibId, controller.tree.selected.getID(), newData, maxItemsNumber, id, function(newItemId){
                    var newItemData, newItem;
                    newItemData = {id: newItemId, content: newData, code: maxItemsNumber};
                    newItem = createObj.newItem(newItemData);
                    newItem.count = 1;
                    totalItems.items[totalItems.prefix + newItemId] = newItem;
                    totalItems.itemsArr.push(newItem);
                    var index = tools.getIndex(controller.tree.selected.items, id, 'item');
                    controller.tree.selected.items.splice(index, 1);
                    controller.tree.selected.items.splice(index, 0, {item: newItem, serialNo: serialNo});
                    tools.orderReshowData(sheet, controller.tree.selected.items, setting, 'item', true);
                });
            }
            else {
                tools.alertOpr(args, sheet, '该编号不存在，请重新输入！', controller.tree.selected.items, 'item');
            }
        }
    },
    upMove: function (controller, sheet) {
        let updateSelArr = [];
        $('#upMove').attr('doing', 'true');
        tools.btnClose($('#upMove'));
        let tempSerialNo = controller.tree.selected.items[controller.tree.selected.args.row].serialNo;
        controller.tree.selected.items[controller.tree.selected.args.row].serialNo = controller.tree.selected.items[controller.tree.selected.args.row -1].serialNo;
        controller.tree.selected.items[controller.tree.selected.args.row -1].serialNo = tempSerialNo;
        updateSelArr.push({id: controller.tree.selected.items[controller.tree.selected.args.row].item.data.id, serialNo: controller.tree.selected.items[controller.tree.selected.args.row].serialNo});
        updateSelArr.push({id: controller.tree.selected.items[controller.tree.selected.args.row -1].item.data.id, serialNo: controller.tree.selected.items[controller.tree.selected.args.row -1].serialNo});
        billsAjax.updateSerialNo(billsLibId, controller.tree.selected.getID(), updateSelArr, 'items', function () {
            tools.orderReshowData(sheet, controller.tree.selected.items, itemsSetting, 'item', true);
            sheet.setActiveCell(controller.tree.selected.args.row -1, controller.tree.selected.args.col);
            controller.tree.selected.args.row = controller.tree.selected.args.row -1;
            $('#upMove').attr('doing', 'false');
            if(tools.canUpMove(controller.tree.selected.items[controller.tree.selected.args.row], controller.tree.selected.items)){
                $('#upMove').attr('canMove', 'true');
                tools.btnAction($('#upMove'));
            }
            else{
                $('#upMove').attr('canMove', 'false');
            }
            if(tools.canDownMove(controller.tree.selected.items[controller.tree.selected.args.row], controller.tree.selected.items)){
                $('#downMove').attr('canMove', 'true');
                tools.btnAction($('#downMove'));
            }
            else{
                $('#downMove').attr('canMove', 'false');
                tools.btnClose($('#downMove'));
            }
        });
    },
    downMove: function (controller, sheet) {
        let updateSelArr = [];
        $('#downMove').attr('doing', 'true');
        tools.btnClose($('#downMove'));
        let tempSerialNo = controller.tree.selected.items[controller.tree.selected.args.row].serialNo;
        controller.tree.selected.items[controller.tree.selected.args.row].serialNo = controller.tree.selected.items[controller.tree.selected.args.row + 1].serialNo;
        controller.tree.selected.items[controller.tree.selected.args.row + 1].serialNo = tempSerialNo;
        updateSelArr.push({id: controller.tree.selected.items[controller.tree.selected.args.row].item.data.id, serialNo: controller.tree.selected.items[controller.tree.selected.args.row].serialNo});
        updateSelArr.push({id: controller.tree.selected.items[controller.tree.selected.args.row + 1].item.data.id, serialNo: controller.tree.selected.items[controller.tree.selected.args.row +1].serialNo});
        billsAjax.updateSerialNo(userAccount, billsLibId, controller.tree.selected.getID(), updateSelArr, 'items', function () {
            tools.orderReshowData(sheet, controller.tree.selected.items, itemsSetting, 'item', true);
            sheet.setActiveCell(controller.tree.selected.args.row +1, controller.tree.selected.args.col);
            controller.tree.selected.args.row = controller.tree.selected.args.row +1;
            $('#downMove').attr('doing', 'false');
            if(tools.canDownMove(controller.tree.selected.items[controller.tree.selected.args.row], controller.tree.selected.items)){
                $('#downMove').attr('canMove', 'true');
                tools.btnAction($('#downMove'));
            }
            else{
                $('#downMove').attr('canMove', 'false');
            }
            if(tools.canUpMove(controller.tree.selected.items[controlle.tree.selected.args.row], controller.tree.selected.items)){
                $('#upMove').attr('canMove', 'true');
                tools.btnAction($('#upMove'));
            }
            else{
                $('#upMove').attr('canMove', 'false');
                tools.btnClose($('#upMove'));
            }
        });
    }

};

var valueController = {
    currentEditData: null,
    onEditStart: function (sender, args) {
        let me = valueController;
        me.currentEditData = args.sheet.getValue(args.row, args.col);
    },
    onEditEnded: function (sender, args) {
        let me = valueController;
        let totalItems = totalItemsController.totalItems;
        let sheet = args.sheet;
        let setting = eigenValueSetting;
        var newValue = args.editingText, tagId = sheet.getTag(args.row, args.col), field, isRepeat;
        setting.cols.forEach(function(col, colIdx){
            if(args.col === colIdx){
                field = col.data.field;
            }
        });
        if(selectedId && newValue!== me.currentEditData){
            isRepeat = tools.isRepeat(valueController.getValues(totalItems, selectedId), field, newValue, 'document');
            if(!tagId && !isRepeat && newValue){//create
                valueController.createValue(sheet, totalItems, selectedId, field, newValue, args);
            }
            else if(tagId && !isRepeat){//update
                valueController.updateValue(totalItems, tagId, newValue, field, args);
            }
            if(isRepeat){
                if(tagId && newValue){
                    sheet.getCell(args.row, args.col, GC.Spread.Sheets.SheetArea.viewport).value(me.currentEditData);
                }
                else {
                    sheet.getCell(args.row, args.col, GC.Spread.Sheets.SheetArea.viewport).value('');
                }
            }
        }
        else{
            sheet.getCell(args.row, args.col).value(me.currentEditData ? me.currentEditData : '');
        }
    },
    editData: function(sheet){
        let me = valueController;
        sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.onEditStart);
        sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
    },
    createValue: function(sheet, totalItems, id, field, newValue, args){
        var newData;
        if(field === 'value'){
            var newCode = valueController.getCode(totalItems, id);
            newData = {code: newCode, value: newValue};
            totalItems.findItem(id).data.itemValue.push(newData);
            let valueArr = valueController.getValues(totalItems, id);
            tools.reshowValue(args.sheet, valueArr, eigenValueSetting, true);
           // tools.reSetCell(sheet, sheet.getActiveRowIndex(), 0, newCode, newCode);
        }
        else {
            if(!isNaN(newValue)){
                newData = {code: newValue, value: ''};
                totalItems.findItem(id).data.itemValue.push(newData);
                let valueArr = valueController.getValues(totalItems, id);
                tools.reshowValue(args.sheet, valueArr, eigenValueSetting, true);
                //tools.reSetCell(sheet, sheet.getActiveRowIndex(), null, null, newValue);
            }
            else {
                //编号只能为数字!
                sheet.getCell(args.row, args.col).value('');
            }
        }
        itemsAjax.updateValue(userAccount, billsLibId, id, newData, null, 'create');
        valueDatas = tools.getsheetDatas(sheet, 'total');
    },

    updateValue: function(totalItems, tagId, newData, field, args){
        var updateData = {code: tagId, newData: newData, field: field};
        var itemVals = totalItems.findItem(selectedId).data.itemValue;
        if(field === 'value'){
            var updateEle = {code: tagId, value: newData};
            if(itemVals){
                var index;
                itemVals.forEach(function(val){
                    if(val.code === tagId){
                        index = itemVals.indexOf(val);
                        itemVals.splice(index, 1);
                    }
                });
                itemVals.splice(index, 0, updateEle);
            }
            itemsAjax.updateValue(userAccount, billsLibId, selectedId, updateData, null, 'update');
        }
        else {
            if(isNumber(newData)){
                if(itemVals){
                    var updateEle;
                    var index;
                    itemVals.forEach(function(val){
                        if(val.code === tagId){
                            updateEle = {code: parseInt(newData), value: val.value};
                            index = itemVals.indexOf(val);
                            itemVals.splice(index, 1);
                        }
                    });
                    itemVals.splice(index, 0, updateEle);
                }
                tools.reshowValue(args.sheet, itemVals, eigenValueSetting, true);
                itemsAjax.updateValue(userAccount, billsLibId, selectedId, updateData, null, 'update');
            }
            else {
                //编号只能为数字!
                args.sheet.getCell(args.row, args.col).value(args.sheet.getValue(0, args.col) ? args.sheet.getValue(0, args.col) : '');
            }
        }
    },

    getValues: function(totalItems, id){
        return totalItems.findItem(id).data.itemValue;
    },

    getTopItem: function(totalItems){
        tools.resort(totalItems.itemsArr, 'code', false);
        return totalItems.itemsArr.length > 0 ? totalItems.itemsArr[0] : null
    },

    getCode: function(totalItems, id){
        var valArr = totalItems.findItem(id).data.itemValue;
        if(valArr){
            tools.resort(valArr, 'code', true);
            return valArr.length > 0 ? parseInt(valArr[valArr.length - 1].code) + 1 : 1;
        }else {
            return 1;
        }

    },

    isRepeat: function(arr, newValue){
        var isRepeat = false;
        arr.forEach(function(itemValue){
            if(itemValue.value === newValue){
                isRepeat = true;
            }
        });
        return isRepeat;
    }
};

var totalJobsController = {
    currentEditData: null,
    totalJobs: null,
    onEditStart: function (sender, args) {
        let me = totalJobsController;
        me.currentEditData = args.sheet.getValue(args.row, args.col);
    },
    onEditEnded: function (sender, args) {
        let me = totalJobsController;
        let totalJobs = me.totalJobs;
        let sheet = args.sheet;
        let setting = totalJobsSetting;
        var newData = args.editingText, tagId = sheet.getTag(args.row, args.col), field, isRepeat;
        setting.cols.forEach(function(col, colIdx){
            if(args.col === colIdx){
                field = col.data.field;
            }
        });
        if(newData != me.currentEditData){
            isRepeat = tools.isRepeat(totalJobs.jobsArr, field, newData, 'reference', null);
            if(!tagId && !isRepeat && newData){//create
                totalJobsController.createJob(sheet, totalJobs, field, newData, args);
            }
            else if(tagId && !isRepeat){//update
                totalJobsController.updateJob(totalJobs, tagId, field, newData, args);
            }
            if(isRepeat){
                tools.alertTotalOpr(args, '该工作内容已存在！', totalJobs.jobsArr);
            }
        }
        else{
            sheet.getCell(args.row, args.col).value(me.currentEditData ? me.currentEditData : '');
        }
    },
    editData: function(sheet){
        let me = totalJobsController;
        sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.onEditStart);
        sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
    },

    createJob: function(sheet, totalJobs, field, newData, args){
        if(field === 'content'){
            maxJobsNumber++;
            let code = maxJobsNumber;
            jobsAjax.createJobContent(userAccount, billsLibId, newData, code, function(newJobId){
                let newJobData, newJob;
                newJobData = {id: newJobId, content: newData, code: code};
                newJob = createObj.newJob(newJobData);
                totalJobs.jobsArr.push(newJob);
                //tools.reSetCell(sheet, args.row, 0, code, newJobId);
                tools.reshowData(sheet, totalJobs.jobsArr, totalJobsSetting, true);
                setSheet.setMaxRowCount(sheet, totalJobs.jobsArr);
                sheetJobsDatas = tools.getsheetDatas(sheet, 'total');
            });
        }
        else {
            let parseNum = parseInt(newData);
            //if(typeof newData === 'number'){
            if(!isNaN(parseNum)){
                maxJobsNumber = maxJobsNumber >= newData ? maxJobsNumber : newData;
                jobsAjax.createJobContent(userAccount, billsLibId, '', newData, function(newJobId){
                    let newJobData, newJob;
                    newJobData = {id: newJobId, content: '', code: newData};
                    newJob = createObj.newJob(newJobData);
                    totalJobs.jobsArr.push(newJob);
                    //tools.reSetCell(sheet, args.row, 0, null, newJobId);
                    tools.reshowData(sheet, totalJobs.jobsArr, totalJobsSetting, true);
                    setSheet.setMaxRowCount(sheet, totalJobs.jobsArr);
                    sheetJobsDatas = tools.getsheetDatas(sheet, 'total');
                });
            }
            else {
                //编号只能为数字!
                tools.alertTotalOpr(args, '编号只能为数字，请重新输入!', totalJobs.jobsArr);
               // sheet.getCell(args.row, args.col).value("");
            }
        }
    },

    updateJob: function(totalJobs, id, field, newData, args){
       // if(field === 'code' && typeof newData !== 'number'){
        if(field === 'code' && isNaN(parseInt(newData))){
            tools.alertTotalOpr(args, '编号只能为数字，请重新输入!', totalJobs.jobsArr);
        }
        else {
            totalJobs.jobsArr.forEach(function(job){
                if(job.data.id === id){
                    job.data[field] = newData;
                }
            });
            tools.reshowData(args.sheet, totalJobs.jobsArr, totalJobsSetting, true);
            jobsAjax.updateJobContent(userAccount, billsLibId, id, field, newData);
        }
    }
};

var totalItemsController = {
    currentEditData: null,
    totalItems: null,
    onEditStart: function (sender, args) {
        let me = totalItemsController;
        me.currentEditData = args.sheet.getValue(args.row, args.col);
    },
    onEditEnded: function (sender, args) {
        let me = totalItemsController;
        let totalItems = me.totalItems;
        let sheet = args.sheet;
        let setting = totalItemsSetting;
        var newData = args.editingText, tagId = sheet.getTag(args.row, args.col), field, isRepeat;
        setting.cols.forEach(function(col, colIdx){
            if(args.col === colIdx){
                field = col.data.field;
            }
        });
        if(newData != me.currentEditData){
            isRepeat = tools.isRepeat(totalItems.itemsArr, field, newData, 'reference', null);
            if(!tagId && !isRepeat && newData){//create
                totalItemsController.createItem(sheet, totalItems, field, newData, args);
            }
            else if(tagId && !isRepeat ){//update
                totalItemsController.updateItem(totalItems, tagId, field, newData, args);
            }
            else if(isRepeat){
                tools.alertTotalOpr(args, '该项目特征已存在！', totalItems.itemsArr);
            }
        }
        else{
            sheet.getCell(args.row, args.col).value(me.currentEditData ? me.currentEditData : '');
        }
    },
    editData: function(sheet){
        let me = totalItemsController;
        sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.onEditStart);
        sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
    },

    createItem: function(sheet, totalItems, field, newData, args){
        if(field === 'content'){
            maxItemsNumber++;
            let code = maxItemsNumber;
            itemsAjax.createItemCharacter(userAccount, billsLibId, newData, code, function(newItemId){
                var newItemData, newItem;
                newItemData = {id: newItemId, content: newData, code: code, itemValue: []};
                newItem = createObj.newItem(newItemData);
                totalItems.itemsArr.push(newItem);
                totalItems.items[totalItems.prefix + newItemId] = newItem;
                //tools.reSetCell(sheet, args.row, 0, code, newItemId);
                tools.reshowData(sheet, totalItems.itemsArr, totalItemsSetting, true);
                setSheet.setMaxRowCount(sheet, totalItems.itemsArr);
                totalItemsDatas = tools.getsheetDatas(sheet, 'total');
            });
        }
        else {
            if(!isNaN(parseInt(newData))){
                maxItemsNumber = maxItemsNumber >= newData ? maxItemsNumber : newData;
                itemsAjax.createItemCharacter(userAccount, billsLibId, '', newData, function(newItemId){
                    var newItemData, newItem;
                    newItemData = {id: newItemId, content: '', code: newData, itemValue: []};
                    newItem = createObj.newItem(newItemData);
                    totalItems.itemsArr.push(newItem);
                    totalItems.items[totalItems.prefix + newItemId] = newItem;
                    //tools.reSetCell(sheet, args.row, 0, null, newItemId);
                    tools.reshowData(sheet, totalItems.itemsArr, totalItemsSetting, true);
                    setSheet.setMaxRowCount(sheet, totalItems.itemsArr);
                    totalItemsDatas = tools.getsheetDatas(sheet, 'total');
                });
            }
            else {
                tools.alertTotalOpr(args, '编号只能为数字，请重新输入！', totalItems.itemsArr);
            }
        }
    },

    updateItem: function(totalItems, id, field, newData, args){
        if(field === 'code' && isNaN(parseInt(newData))){
            tools.alertTotalOpr(args, '编号只能为数字，请重新输入！', totalItems.itemsArr);
        }
        else {
            totalItems.itemsArr.forEach(function(item){
                if(item.data.id === id){
                    item.data[field] = newData;
                }
            });
            tools.reshowData(args.sheet, totalItems.itemsArr, totalItemsSetting, true);
            itemsAjax.updateItemCharacter(userAccount, billsLibId, id, field, newData);
        }
    }
};

var rechargeController = {
    updateRechar: function(selectedNode, newData){
        if(selectedNode){
            var  updateId = selectedNode.getID();
            selectedNode.data.recharge = newData;
            /*var getupdateIds = function(node){
                updateIds.push(node.getID());
                node.data.recharge = newData;
                if(node.children.length > 0){
                    node.children.forEach(function(node){
                        getupdateIds(node);
                    });
                }
            }
            getupdateIds(tools.getRoot(selectedNode));*/
            billsAjax.updateRecharge(userAccount, billsLibId, updateId, newData);
        }
        else {
            codeEditor.setValue('');
            //$('exampleTextarea').val('');
        }
    },
    createRecharge: function(node){
        if(node){
            var tempId = [];
            tempId.push(node.getID());
            var rootNode = tools.getRoot(node);
            if(rootNode.data.recharge && rootNode !== node){
                billsAjax.updateRecharge(userAccount, billsLibId, tempId, rootNode.data.recharge);
                node.data.recharge = rootNode.data.recharge;
                //$('#exampleTextarea').val(node.data.recharge);
                codeEditor.setValue(node.data.recharge);
            }
            else {
                node.data.recharge = '';
                //$('#exampleTextarea').val('');
                codeEditor.setValue('');
            }
        }
        else {
            codeEditor.setValue('');
            //$('exampleTextarea').val('');
        }
    }
};

function isNumber(num){
    return !isNaN(num) && num % 1 === 0;
}




