/**
 * Created by Zhong on 2018/1/16.
 */
let gljClassTreeObj = {
    cache: null,//ref to tree.items
    tree: null,
    controller: null,
    workBook: null,
    sheet: null,
    updateType: {new: 'new', update: 'update'},
    insertBtn: $('#tree_Insert'),
    removeBtn: $('#tree_remove'),
    upLevelBtn: $('#tree_upLevel'),
    downLevelBtn: $('#tree_downLevel'),
    downMoveBtn: $('#tree_downMove'),
    upMoveBtn: $('#tree_upMove'),
    setting: {
        sheet: {
            cols:[
                {
                    head: {
                        titleNames: ['名称'],
                        spanCols: [1],
                        spanRows: [2],
                        vAlign: [1, 1],
                        hAlign: [1, 1],
                        font: 'Arial'
                    },
                    data: {
                        field: 'Name',
                        vAlign: 1,
                        hAlign: 0,
                        font: 'Arial'
                    },
                    width: 400
                }
            ],
            headRows: 1,
            headRowHeight: [30],
            emptyRows: 0,
            treeCol: 0
        },
        tree: {
            id: 'ID',
            pid: 'ParentID',
            nid: 'NextSiblingID',
            rootId: -1
        },
        options: {
            tabStripVisible:  false,
            allowContextMenu: false,
            allowCopyPasteExcelStyle : false,
            allowExtendPasteRange: false,
            allowUserDragDrop : false,
            allowUserDragFill: false,
            scrollbarMaxAlign : true
        }
    },

    isDef: function (v) {
        return v !== undefined && v !== null;
    },
    isFunc: function (v) {
        return this.isDef(v) && typeof v === 'function';
    },
    //sheet things
    setOptions: function (workbook, opts) {
        for(let opt in opts){
            workbook.options[opt] = opts[opt];
        }
    },

    renderFunc: function (sheet, func) {
        sheet.suspendPaint();
        sheet.suspendEvent();
        if(this.isFunc(func)){
            func();
        }
        sheet.resumePaint();
        sheet.resumeEvent();
    },

    buildSheet: function () {
        if(!this.isDef(this.workBook)){
            this.workBook = new GC.Spread.Sheets.Workbook($('#gljClassSpread')[0], {sheetCount: 1});
            this.sheet = this.workBook.getActiveSheet();
            this.setOptions(this.workBook, this.setting.options);
            this.sheet.options.clipBoardOptions = GC.Spread.Sheets.ClipboardPasteOptions.values;
            this.bindEvents(this.sheet);
        }
    },

    bindEvents: function (sheet) {
        let me = gljClassTreeObj;
        const Events = GC.Spread.Sheets.Events;
        sheet.bind(Events.SelectionChanged, me.onSelectionChanged);
        sheet.bind(Events.EditEnded, me.onEditEnded);
        sheet.bind(Events.ClipboardPasted, me.onClipboardPasted);
    },

    onSelectionChanged: function (sender, info) {
        let me = gljClassTreeObj;
        if(info.oldSelections.length === 0 && info.newSelections.length > 0 || info.oldSelections[0].row !== info.newSelections[0].row){
            let row = info.newSelections[0].row;
            let node = me.cache[row];
            me.initSelection(node);
        }
        else {
            me.refreshBtn(null);
        }
    },

    onEditEnded: function (sender, args) {
        let me = gljClassTreeObj;
        let postData = [];
        let v = me.isDef(args.editingText) ? args.editingText.toString().trim() : '';
        let node = me.cache[args.row];
        if(me.isDef(node) && node.data.Name !== v){
            let updateObj = me.getUpdateObj(me.updateType.update, node.getID(), null, null, v, null);
            postData.push(updateObj);
            //ajax
            //update
            me.gljClassTreeAjax(postData, function (rstData) {
                node.data.Name = v;
            }, function () {
                args.sheet.setValue(args.row, args.col, node.data.Name ? node.data.Name : '');
            });
        }
    },

    onClipboardPasted: function (sender, info) {
        let me = gljClassTreeObj;
        let items = sheetCommonObj.analyzePasteData({header: [{dataCode: 'Name'}]}, info);
        let postData = [];
        let frontData = [];
        for(let i = 0, len = items.length; i < len; i++){
            let row = info.cellRange.row + i;
            let node = me.cache[row];
            if(me.isDef(node) && me.isDef(items[i].Name) && node.data.Name !== items[i].Name){
                let updateObj = me.getUpdateObj(me.updateType.update, node.getID(), null, null, items[i].Name, null);
                postData.push(updateObj);
                frontData.push({row: row, Name: items[i].Name});
                node.data.Name = items[i].Name;
            }
        }
        if(postData.length > 0){
            //ajax
            me.gljClassTreeAjax(postData, function (rstData) {
                for(let i = 0, len = frontData.length; i < len; i++){
                    let node = me.cache[frontData[i]['row']];
                    if(me.isDef(node)){
                        node.data.Name = frontData[i]['Name'];
                    }
                }
            }, function () {
                for(let i = 0, len = frontData.length; i < len; i++){
                    let node = me.cache[frontData[i]['row']];
                    me.sheet.setValue(frontData[i]['row'], 0, me.isDef(node) ? node.data.Name : '');
                }
            });
        }
    },

    getGljClassTree: function (gljLibId, callback) {
        let me = gljClassTreeObj;
        let re = repositoryGljObj;
        let url = 'api/getGljTree';
        let postData = {gljLibId: gljLibId};
        let sucFunc = function (rstData) {
            zTreeHelper.createTree(rstData, componentSetting, "componentTree", componentOprObj);
            let rootNode = componentOprObj.treeObj.getNodes()[0];
            if(rootNode && rootNode.isParent && rootNode.isFirstNode){
                componentOprObj.rootNode = rootNode;
            }
            if (rstData && rstData.length > 0) {
                me.gljCurTypeId = rstData[0].ID;
            }
            //init
            me.buildSheet();
            me.initTree(rstData);
            me.cache = me.tree.items;
            re.updateParentNodeIds(me.cache, re);
            me.bindBtn();
            me.initController(me.tree, me.sheet, me.setting.sheet);
            me.controller.showTreeData();
            me.sheet.setFormatter(-1, 0, '@');
            me.initSelection(me.tree.selected);
            if(callback){
                callback();
            }
        };
        let errFunc = function () {

        };
        CommonAjax.post(url, postData, sucFunc, errFunc);
    },

    initTree: function (datas) {
        this.tree = idTree.createNew(this.setting.tree);
        this.tree.loadDatas(datas);
        this.tree.selected = this.tree.items.length > 0 ? this.tree.items[0] : null;
    },

    initController: function (tree, sheet, setting) {
        this.controller = TREE_SHEET_CONTROLLER.createNew(tree, sheet, setting);
    },

    refreshBtn: function (selected) {
        if (locked) {
            return;
        }
        let me = this;
        me.insertBtn.removeClass('disabled');
        me.removeBtn.removeClass('disabled');
        me.upLevelBtn.removeClass('disabled');
        me.downLevelBtn.removeClass('disabled');
        me.downMoveBtn.removeClass('disabled');
        me.upMoveBtn.removeClass('disabled');
        if(!me.isDef(selected)){
            me.removeBtn.addClass('disabled');
            me.upLevelBtn.addClass('disabled');
            me.downLevelBtn.addClass('disabled');
            me.downMoveBtn.addClass('disabled');
            me.upMoveBtn.addClass('disabled');
        }
        else {
            if(!me.isDef(selected.preSibling)){
                me.downLevelBtn.addClass('disabled');
                me.upMoveBtn.addClass('disabled');
            }
            if(!me.isDef(selected.nextSibling)){
                me.downMoveBtn.addClass('disabled');
            }
            if(!me.isDef(selected.parent)){
                me.upLevelBtn.addClass('disabled');
            }
        }
    },

    bindBtn: function () {
        let me = this;
        me.insertBtn.click(function () {
            me.insert();
        });
        $('#delConfirm').click(function () {
            if(me.canRemoveClass){
                me.remove(me.tree.selected);
            }
            $('#delAlert').modal('hide');
        });
        me.removeBtn.click(function () {
            //当前分类下无子项且无工料机数据，才允许删除
            let classNode = me.cache[me.workBook.getActiveSheet().getActiveRowIndex()];
            if(!classNode){
                return;
            }
            let className = me.isDef(classNode.data.Name) ? classNode.data.Name : '';
            let classGljs = repositoryGljObj.currentCache;
            if(classNode.children.length > 0 || (classGljs && classGljs.length > 0)){
                me.canRemoveClass = false;
                $('#delAlert').find('.modal-body h5').text('当前分类下有数据，不可删除。');
            }
            else {
                me.canRemoveClass = true;
                $('#delAlert').find('.modal-body h5').text(`确认要删除分类 “${className}”吗？`);
            }
            $('#delAlert').modal('show');
        });
        me.upLevelBtn.click(function () {
            me.upLevel(me.tree.selected);
        });
        me.downLevelBtn.click(function () {
            me.downLevel(me.tree.selected);
        });
        me.downMoveBtn.click(function () {
            me.downMove(me.tree.selected);
        });
        me.upMoveBtn.click(function () {
            me.upMove(me.tree.selected);
        });
    },

    insert: function () {
        let me = this;
        let re = repositoryGljObj;
        me.insertBtn.addClass('disabled');
        let postData = [];
        let newID = me.tree.newNodeID();
        if(!me.isDef(newID)){
            return;
        }
        let selected = me.tree.selected;
        let insertObj = me.getUpdateObj(me.updateType.new, newID, -1, -1, '', null);
        if(me.isDef(selected)) {
            let updateObj = me.getUpdateObj(me.updateType.update, selected.getID(), newID, null, null, null);
            postData.push(updateObj);
            insertObj.updateData.ParentID = selected.getParentID();
            if(me.isDef(selected.nextSibling)){
                insertObj.updateData.NextSiblingID = selected.getNextSiblingID();
            }
        }
        postData.push(insertObj);
        if(postData.length > 0){
            //ajax
            me.gljClassTreeAjax(postData, function (rstData) {
                me.controller.insert();
                me.refreshBtn(me.tree.selected);
                //fresh tools
                re.updateParentNodeIds(me.cache, re);
                me.initSelection(me.tree.selected);
            });
        }
    },
    remove: function (selected) {
        let me = this;
        let re = repositoryGljObj;
        me.removeBtn.addClass('disabled');
        let postData = [], IDs = [];
        if(!selected){
            return;
        }
        getDelIds(selected);
        function getDelIds(node){
            if(me.isDef(node)){
                IDs.push(node.getID());
                if(node.children.length > 0){
                    for(let i = 0, len = node.children.length; i < len; i++){
                        getDelIds(node.children[i]);
                    }
                }
            }
        }
        if(me.isDef(selected.preSibling)){
            let updateObj = me.getUpdateObj(me.updateType.update, selected.preSibling.getID(), selected.getNextSiblingID(), null, null, null);
            postData.push(updateObj);
        }
        if(IDs.length > 0){
            for(let i = 0, len = IDs.length; i < len; i++){
                let delObj = me.getUpdateObj(me.updateType.update, IDs[i], null, null, null, true);
                postData.push(delObj);
            }
        }
        if(postData.length > 0){
            //ajax
            me.gljClassTreeAjax(postData, function (rstData) {
                me.controller.delete();
                me.refreshBtn(me.tree.selected);
                re.updateParentNodeIds(me.cache, re);
                me.initSelection(me.tree.selected);
                me.workBook.getActiveSheet().setActiveCell(me.tree.selected ? me.tree.selected.serialNo() : 0, 0);
            });
        }
    },
    upLevel: function (selected) {
        let me = this;
        let re = repositoryGljObj;
        me.upLevelBtn.addClass('disabled');
        let postData = [];
        if(!me.isDef(selected)){
            return;
        }
        if(!me.isDef(selected.parent)){
            return;
        }
        if(me.isDef(selected.preSibling)){
            let updateObj = me.getUpdateObj(me.updateType.update, selected.preSibling.getID(), -1, null, null, null);
            postData.push(updateObj);
        }
        let updateObj = me.getUpdateObj(me.updateType.update, selected.getID(), selected.parent.getNextSiblingID(), selected.parent.getParentID(), null, null);
        postData.push(updateObj);
        let updateParent = me.getUpdateObj(me.updateType.update, selected.getParentID(), selected.getID(), null, null, null);
        postData.push(updateParent);
        let nextIDs = [];
        getNext(selected);
        function getNext(node){
            if(me.isDef(node.nextSibling)){
                nextIDs.push(node.getNextSiblingID());
                getNext(node.nextSibling);
            }
        }
        for(let i = 0, len = nextIDs.length; i < len; i++){
            postData.push(me.getUpdateObj(me.updateType.update, nextIDs[i], null, selected.getID(), null, null));
        }
        if(postData.length > 0){
            //ajax
            me.gljClassTreeAjax(postData, function (rstData) {
                me.controller.upLevel();
                me.refreshBtn(me.tree.selected);
                re.updateParentNodeIds(me.cache, re);
            });
        }

    },
    downLevel: function (selected) {
        let me = this;
        let re = repositoryGljObj;
        me.downLevelBtn.addClass('disabled');
        let postData = [];
        if(!me.isDef(selected)){
            return;
        }
        if(!me.isDef(selected.preSibling)){
            return;
        }
        let updatePre = me.getUpdateObj(me.updateType.update, selected.preSibling.getID(), selected.getNextSiblingID(), null, null, null);
        postData.push(updatePre);
        if(selected.preSibling.children.length > 0){
            let updateObj = me.getUpdateObj(me.updateType.update, selected.preSibling.children[selected.preSibling.children.length - 1].getID(), selected.getID(), null, null, null);
            postData.push(updateObj);
        }
        let updateObj = me.getUpdateObj(me.updateType.update, selected.getID(), -1, selected.preSibling.getID(), null, null);
        postData.push(updateObj);
        if(postData.length > 0){
            //ajax
            me.gljClassTreeAjax(postData, function (rstData) {
                me.controller.downLevel();
                me.refreshBtn(me.tree.selected);
                re.updateParentNodeIds(me.cache, re);
            });
        }
    },
    upMove: function (selected) {
        let me = this;
        me.upMoveBtn.addClass('disabled');
        let postData = [];
        if(!me.isDef(selected)){
            return;
        }
        if(!me.isDef(selected.preSibling)){
            return;
        }
        let updateObj = me.getUpdateObj(me.updateType.update, selected.getID(), selected.preSibling.getID(), null, null, null);
        postData.push(updateObj);
        let updatePre = me.getUpdateObj(me.updateType.update, selected.preSibling.getID(), selected.getNextSiblingID(), null, null, null);
        postData.push(updatePre);
        if(me.isDef(selected.preSibling.preSibling)){
            let updatePrepre = me.getUpdateObj(me.updateType.update, selected.preSibling.preSibling.getID(), selected.getID(), null, null, null);
            postData.push(updatePrepre);
        }
        if(postData.length > 0){
            //ajax
            me.gljClassTreeAjax(postData, function (rstData) {
                me.controller.upMove();
                me.refreshBtn(me.tree.selected);
            });
        }
    },
    downMove: function (selected) {
        let me = this;
        me.downMoveBtn.addClass('disabled');
        let postData = [];
        if(!me.isDef(selected)){
            return;
        }
        if(!me.isDef(selected.nextSibling)){
            return;
        }
        if(me.isDef(selected.preSibling)){
            let updatePre = me.getUpdateObj(me.updateType.update, selected.preSibling.getID(), selected.getNextSiblingID(), null, null, null);
            postData.push(updatePre);
        }
        let updateObj = me.getUpdateObj(me.updateType.update, selected.getID(), selected.nextSibling.getNextSiblingID(), null, null, null);
        postData.push(updateObj);
        let updateNext = me.getUpdateObj(me.updateType.update, selected.getNextSiblingID(), selected.getID(), null, null, null);
        postData.push(updateNext);
        if(postData.length > 0){
            //ajax
            me.gljClassTreeAjax(postData, function (rstData) {
                me.controller.downMove();
                me.refreshBtn(me.tree.selected);
            });
        }
    },
    getUpdateObj: function (updateType, id, nid, pid, name, deleted) {
        let updateObj = Object.create(null);
        updateObj.updateType = '';
        updateObj.updateData = Object.create(null);
        updateObj.updateData.repositoryId = pageOprObj.gljLibId;
        if(this.isDef(updateType)){
            updateObj.updateType = updateType;
        }
        if(this.isDef(id)){
            updateObj.updateData.ID = id;
        }
        if(this.isDef(nid)){
            updateObj.updateData.NextSiblingID = nid;
        }
        if(this.isDef(pid)){
            updateObj.updateData.ParentID = pid;
        }
        if(this.isDef(name)){
            updateObj.updateData.Name = name;
        }
        if(this.isDef(deleted)){
            updateObj.updateData.deleted = true;
        }
        return updateObj;
    },
    gljClassTreeAjax: function (postData, scFunc, errFunc) {
        CommonAjax.post('api/updateNodes', {updateData: postData, lastOpr: userAccount}, scFunc, errFunc);
    },
    //模仿默认点击
    initSelection: function (node) {
        let me = this,
            re = repositoryGljObj,
            that = gljComponentOprObj;
        me.refreshBtn(node);
        if(!re.isDef(node)){
            return;
        }
        let gljTypeId = node.data.ID;
        re.gljCurTypeId = node.data.ID;
        re.addGljObj = null;
        sheetCommonObj.cleanSheet(that.workBook.getSheet(0), that.setting, 10);
        if (re.parentNodeIds["_pNodeId_" + gljTypeId]) {
            re.currentOprParent = 1;
            re.currentCache = re.getParentCache(re.parentNodeIds["_pNodeId_" + gljTypeId]);
            re.workBook.getSheet(0).setRowCount(re.currentCache.length);
        } else {
            re.currentOprParent = 0;
            re.currentCache = re.getCache();
        }
        re.showGljItems(re.currentCache, gljTypeId);
        me.workBook.focus(true);
    }
}