/**
 * Created by Mai on 2017/4/1.
 */

var TREE_SHEET_HELPER = {
    getObjPos: function (obj) {
        let target = obj;
        let pos = {x: obj.offsetLeft, y: obj.offsetTop};

        target = obj.offsetParent;
        while (target) {
            pos.x += target.offsetLeft;
            pos.y += target.offsetTop;
            target = target.offsetParent;
        }
        return pos;
    },
    /**
     * 初始化setting,需要提示单元格text时,必须先初始化setting
     * @param obj
     * @param setting
     */
    initSetting: function (obj, setting) {
        setting.pos = this.getObjPos(obj);
    },
    createNewSpread: function (obj) {
        var spread = new GC.Spread.Sheets.Workbook(obj, {sheetCount: 1});
        spread.options.tabStripVisible = false;
        spread.options.scrollbarMaxAlign = true;
        spread.options.cutCopyIndicatorVisible = false;
        spread.options.allowCopyPasteExcelStyle = false;
        spread.options.allowUserDragDrop = false;
        spread.options.allowContextMenu = false;
        spread.options.showDragFillSmartTag = false;
        spread.getActiveSheet().setRowCount(3);
        return spread;
    },
    getSheetCellStyle: function (setting) {
        var style = new GC.Spread.Sheets.Style();
        style.locked = setting.readOnly ? true : false;
        style.name = setting.id;
        style.font = setting.data.font;
        style.hAlign = setting.data.hAlign;
        style.vAlign = setting.data.vAlign;
        style.wordWrap = setting.data.wordWrap;
        if (setting.data.formatter) {
            style.formatter = setting.data.formatter;
        }
        return style;
    },
    loadSheetHeader: function (setting, sheet) {
        if (setting.frozenCols) {
            sheet.frozenColumnCount(setting.frozenCols);
        }
        sheet.setColumnCount(setting.cols.length);
        sheet.setRowCount(setting.headRows, GC.Spread.Sheets.SheetArea.colHeader);
        setting.headRowHeight.forEach(function (rowHeight, index) {
            sheet.setRowHeight(index, rowHeight, GC.Spread.Sheets.SheetArea.colHeader);
        });
        setting.cols.forEach(function (col, index) {
            var i, iRow = 0, cell;
            for (i = 0; i < col.head.spanCols.length; i++) {
                if (col.head.spanCols[i] !== 0) {
                    cell = sheet.getCell(iRow, index, GC.Spread.Sheets.SheetArea.colHeader);
                    cell.value(col.head.titleNames[i]).font(col.head.font).hAlign(col.head.hAlign[i]).vAlign(col.head.vAlign[i]).wordWrap(true);
                }
                if (col.head.spanCols[i] > 1 || col.head.spanRows[i] > 1) {
                    sheet.addSpan(iRow, index, col.head.spanRows[i], col.head.spanCols[i], GC.Spread.Sheets.SheetArea.colHeader);
                }
                iRow += col.head.spanRows[i];
            };
            sheet.setColumnWidth(index, col.width);
        });
    },
    protectdSheet: function (sheet) {
        var option = {
            allowSelectLockedCells: true,
            allowSelectUnlockedCells: true,
            allowResizeRows: true,
            allowResizeColumns: true
        };

        sheet.options.protectionOptions = option;
        sheet.options.isProtected = true;
    },
    massOperationSheet: function (sheet, Operation) {
        sheet.suspendPaint();
        sheet.suspendEvent();
        Operation();
        sheet.resumeEvent();
        sheet.resumePaint();
    },
    refreshNodesVisible: function (nodes, sheet, recursive) {
        nodes.forEach(function (node) {
            var iRow;
            iRow = node.serialNo();
            sheet.setRowVisible(iRow, node.visible, GC.Spread.Sheets.SheetArea.viewport);
            if (recursive) {
                TREE_SHEET_HELPER.refreshNodesVisible(node.children, sheet, recursive);
            }
        })
    },
    refreshTreeNodeData: function (setting, sheet, nodes, recursive) {
        nodes.forEach(function (node) {
            setting.cols.forEach(function (colSetting, iCol) {
                var iRow = node.serialNo();
                var cell = sheet.getCell(iRow, iCol, GC.Spread.Sheets.SheetArea.viewport);

                var getFieldText = function () {
                    var fields = colSetting.data.field.split('.');
                    var validField = fields.reduce(function (field1, field2) {
                        if (eval('node.data.' + field1)) {
                            return field1 + '.' + field2
                        } else {
                            return field1;
                        }
                    });
                    if (eval('node.data.' + validField)) {
                        return eval('node.data.' + validField);
                    } else {
                        return '';
                    }
                };
                var getFieldText2 = function () {
                    var fields = colSetting.data.field.split('.'), iField, data = node.data;
                    for (iField = 0; iField < fields.length; iField++) {
                        if (data[fields[iField]]) {
                            data = data[fields[iField]];
                        } else {
                            return '';
                        }
                    }
                    return data;
                };
                if (colSetting.data.getText && Object.prototype.toString.apply(colSetting.data.getText) === "[object Function]") {
                    cell.value(colSetting.data.getText(node));
                } else {
                    cell.value(getFieldText2());
                }
                if (colSetting.data.cellType && Object.prototype.toString.apply(colSetting.data.cellType) !== "[object String]") {
                    cell.cellType(colSetting.data.cellType);
                }
                if (colSetting.readOnly) {
                    if (Object.prototype.toString.apply(colSetting.readOnly) === "[object Function]") {
                        cell.locked(colSetting.readOnly(node));
                    } else {
                        cell.locked(true);
                    }
                } else {
                    cell.locked(false);
                }
            });
            sheet.autoFitRow(node.serialNo());
            if (recursive) {
                TREE_SHEET_HELPER.refreshTreeNodeData(setting, sheet, node.children, recursive);
            }
        });
    },
    refreshChildrenVisiable:function(sheet,tree,node,row,visiable){
        let iCount = node.posterityCount(), i, child;
        for (i = 0; i < iCount; i++) {
            child = tree.items[row + i +1];
            sheet.setRowVisible(row + i + 1, visiable?visiable:child.visible, GC.Spread.Sheets.SheetArea.viewport);
        }
        sheet.invalidateLayout();
    },
    showTreeData: function (setting, sheet, tree) {
        var indent = 20;
        var halfBoxLength = 5;
        var halfExpandLength = 3;

        var TreeNodeCellType = function () {
        };
        TreeNodeCellType.prototype = new GC.Spread.Sheets.CellTypes.Text();
        TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
            if (style.backColor) {
                ctx.save();
                ctx.fillStyle = style.backColor;
                ctx.fillRect(x, y, w, h);
                ctx.restore();
            } else {
                ctx.clearRect(x, y, w, h);
            }
            // ������(x1, y1)���(��, ��), (x2, y2)�յ�(��, ��), ��ɫ
            var drawLine = function (canvas, x1, y1, x2, y2, color) {
                ctx.save();
                // ����ƫ����
                ctx.translate(0.5, 0.5);
                ctx.beginPath();
                ctx.moveTo(x1, y1);
                ctx.lineTo(x2, y2);
                ctx.strokeStyle = color;
                ctx.stroke();
                ctx.restore();
            };
            var drawExpandBox = function (ctx, x, y, w, h, centerX, centerY, expanded) {
                var rect = {}, h1, h2, offset = 1;
                rect.top = centerY - halfBoxLength;
                rect.bottom = centerY + halfBoxLength;
                rect.left = centerX - halfBoxLength;
                rect.right = centerX + halfBoxLength;

                if (rect.left < x + w) {
                    rect.right = Math.min(rect.right, x + w);

                    ctx.save();
                    // ����ƫ����
                    ctx.translate(0.5, 0.5);
                    ctx.strokeStyle = 'black';
                    ctx.beginPath();
                    ctx.moveTo(rect.left, rect.top);
                    ctx.lineTo(rect.left, rect.bottom);
                    ctx.lineTo(rect.right, rect.bottom);
                    ctx.lineTo(rect.right, rect.top);
                    ctx.lineTo(rect.left, rect.top);
                    ctx.stroke();
                    ctx.fillStyle = 'white';
                    ctx.fill();
                    ctx.restore();

                    // Draw Horizontal Line
                    h1 = centerX - halfExpandLength;
                    h2 = Math.min(centerX + halfExpandLength, x + w);
                    if (h2 > h1) {
                        drawLine(ctx, h1, centerY, h2, centerY, 'black');
                    }
                    // Draw Vertical Line
                    if (!expanded && (centerX < x + w)) {
                        drawLine(ctx, centerX, centerY - halfExpandLength, centerX, centerY + halfExpandLength, 'black');
                    }
                }
            }
            var node = tree.items[options.row];
            var showTreeLine = true;

            if (!node) { return; }

            var iLevel = node.depth();
            var centerX = Math.floor(x) + node.depth() * indent + indent / 2;
            var x1 = centerX + indent / 2;
            var centerY = Math.floor((y + (y + h)) / 2);
            var y1;
            // Draw Sibling Line
            if (showTreeLine) {
                // Draw Horizontal Line
                if (centerX < x + w) {
                    drawLine(ctx, centerX, centerY, Math.min(x1, x + w), centerY, 'gray');
                }
                // Draw Vertical Line
                if (centerX < x + w) {
                    y1 = node.isLast() ? centerY : y + h;
                    if (node.isFirst() && !node.parent) {
                        drawLine(ctx, centerX, centerY, centerX, y1, 'gray');
                    } else {
                        drawLine(ctx, centerX, y, centerX, y1, 'gray');
                    }
                }
            }
            // Draw Expand Box
            if (node.children.length > 0) {
                drawExpandBox(ctx, x, y, w, h, centerX, centerY, node.expanded);
            }
            // Draw Parent Line
            if (showTreeLine) {
                var parent = node.parent, parentCenterX = centerX - indent;
                while (parent) {
                    if (!parent.isLast()) {
                        if (parentCenterX < x + w) {
                            drawLine(ctx, parentCenterX, y, parentCenterX, y + h, 'gray');
                        }
                    }
                    parent = parent.parent;
                    parentCenterX -= indent;
                }
            };
            // Draw Text
            x = x + (node.depth() + 1) * indent;
            w = w - (node.depth() + 1) * indent;
            GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
        };
        TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
            return {
                x: x,
                y: y,
                row: context.row,
                col: context.col,
                cellStyle: cellStyle,
                cellRect: cellRect,
                sheetArea: context.sheetArea
            };
        };
        TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
            var offset = -1;
            var node = tree.items[hitinfo.row];
            tree.selected = node;
            if (!node || node.children.length === 0) { return; }
            var centerX = hitinfo.cellRect.x + offset + node.depth() * indent + indent / 2;
            var centerY = (hitinfo.cellRect.y + offset + (hitinfo.cellRect.y + offset + hitinfo.cellRect.height)) / 2;

            if (hitinfo.x > centerX - halfBoxLength && hitinfo.x < centerX + halfBoxLength && hitinfo.y > centerY - halfBoxLength && hitinfo.y < centerY + halfBoxLength) {
                node.setExpanded(!node.expanded);
                TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () {
                    var iCount = node.posterityCount(), i, child;
                    for (i = 0; i < iCount; i++) {
                        child = tree.items[hitinfo.row + i + 1];
                        hitinfo.sheet.setRowVisible(hitinfo.row + i + 1, child.visible, hitinfo.sheetArea);
                        //hitinfo.sheet.setRowVisible(hitinfo.row + i + 1, child.vis(), hitinfo.sheetArea);
                    }
                    hitinfo.sheet.invalidateLayout();
                });
                hitinfo.sheet.repaint();
            }
        };
        TreeNodeCellType.prototype.processMouseEnter = function(hitinfo){
            if(hitinfo.sheet.name() === 'stdBillsGuidance_bills'){
                TREE_SHEET_HELPER.delayShowTips(hitinfo,setting);
            }
        };
        TreeNodeCellType.prototype.processMouseLeave = function (hitinfo) {
            TREE_SHEET_HELPER.hideTipsDiv();
        };

        let TipCellType = function () {};
        TipCellType.prototype = new GC.Spread.Sheets.CellTypes.Text();
        TipCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
            return {
                x: x,
                y: y,
                row: context.row,
                col: context.col,
                cellStyle: cellStyle,
                cellRect: cellRect,
                sheet: context.sheet,
                sheetArea: context.sheetArea
            };
        };
        TipCellType.prototype.processMouseEnter = function (hitinfo) {
            let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
            if (setting.pos && text && text !== '') {
                if (!this._toolTipElement) {
                    var div = document.createElement("div");
                    $(div).css("position", "absolute")
                        .css("border", "1px #C0C0C0 solid")
                        .css("box-shadow", "1px 2px 5px rgba(0,0,0,0.4)")
                        .css("font", "9pt Arial")
                        .css("background", "white")
                        .css("padding", 5);

                    this._toolTipElement = div;
                }
                $(this._toolTipElement).text(text).css("top", setting.pos.y + hitinfo.y + 15).css("left", setting.pos.x + hitinfo.x + 15);
                $(this._toolTipElement).hide();
                document.body.insertBefore(this._toolTipElement, null);
                $(this._toolTipElement).show("fast");
            }
        };
        TipCellType.prototype.processMouseLeave = function (hininfo) {
            if (this._toolTipElement) {
                document.body.removeChild(this._toolTipElement);
                this._toolTipElement = null;
            }
        }

        TREE_SHEET_HELPER.protectdSheet(sheet);
        TREE_SHEET_HELPER.massOperationSheet(sheet, function () {
            sheet.rowOutlines.direction(GC.Spread.Sheets.Outlines.OutlineDirection.backward);
            sheet.showRowOutline(false);
            if (setting.defaultRowHeight) {
                sheet.defaults.rowHeight = setting.defaultRowHeight;
            }
            sheet.setRowCount(tree.count() + setting.emptyRows, GC.Spread.Sheets.SheetArea.viewport);
            setting.cols.forEach(function (colSetting, iCol) {
                sheet.setStyle(-1, iCol, TREE_SHEET_HELPER.getSheetCellStyle(colSetting));
                if (colSetting.showHint) {
                    sheet.getRange(-1, iCol, -1, 1).cellType(new TipCellType());
                }
            });
            sheet.getRange(-1, setting.treeCol, -1, 1).cellType(new TreeNodeCellType());
            TREE_SHEET_HELPER.refreshTreeNodeData(setting, sheet, tree.roots, true);
            TREE_SHEET_HELPER.refreshNodesVisible(tree.roots, sheet, true);
        });
    },
    showTipsDiv:function (text,setting,hitinfo) {
        if (text && text !== '') {
            if(text) text = replaceAll(/[\n]/,'<br>',text);
            if(!this._fixedTipElement){
                let div = $('#fixedTip')[0];
                if (!div) {
                    div = document.createElement("div");
                    $(div).css("padding", 5)
                        .attr("id", 'fixedTip');
                    $(div).hide();
                    document.body.insertBefore(div, null);
                }
                this._fixedTipElement = div;
            }
            $(this._fixedTipElement).width('');
            $(this._fixedTipElement).html(text);
            if (!this._toolTipElement) {
                let div = $('#autoTip')[0];
                if (!div) {
                    div = document.createElement("div");
                    $(div).css("position", "absolute")
                        .css("border", "1px #C0C0C0 solid")
                        .css("box-shadow", "1px 2px 5px rgba(0,0,0,0.4)")
                        .css("font", "0.9rem Calibri")
                        .css("background", "white")
                        .css("padding", 5)
                    $(div).attr("id", 'autoTip');
                    $(div).hide();
                    document.body.insertBefore(div, null);
                }
                this._toolTipElement = div;
                $(this._toolTipElement).width('');
                //实时读取位置信息
                if(hitinfo.sheet && hitinfo.sheet.getParent().qo){
                    setting.pos = SheetDataHelper.getObjPos(hitinfo.sheet.getParent().qo);
                }
                $(this._toolTipElement).html(`<span>${text}</span><div class="triangle-border tb-border_up"></div><div class="triangle-border tb-background_up"></div>`);
                //清单指引、清单库做特殊处理
                if($(hitinfo.sheet.name === 'stdBillsGuidance_bills')){
                    $(this._toolTipElement).html(`<span>${text}</span>`);
                    let divWidth = $(this._fixedTipElement).width(),
                        divHeight = $(this._fixedTipElement).height();
                    if(divWidth > 600){
                        divWidth = 590;
                        $(this._toolTipElement).width(divWidth);
                    }
                    let top = setting.pos.y  + hitinfo.y - divHeight / 2 < 0 ? 0 : setting.pos.y  + hitinfo.y - divHeight / 2;
                    $(this._toolTipElement).css("top", top).css("left", hitinfo.x + 20);
                } else {
                    //计算显示的初始位置
                    /*   显示在单元格上方，三角形指向下的版本
                     let top = setting.pos.y + hitinfo.cellRect.y -$(this._toolTipElement).height() -26;
                     let left =  setting.pos.x + hitinfo.cellRect.x;
                     $(this._toolTipElement).css("top", top).css("left", left);*/
                    //显示在下方，三角形指
                    let top = setting.pos.y  + hitinfo.cellRect.y+26;
                    let left =  setting.pos.x + hitinfo.cellRect.x;
                    $(this._toolTipElement).css("top", top).css("left", left);

                }
                $(this._toolTipElement).show("fast");
                TREE_SHEET_HELPER.tipDiv = 'show';//做个标记
            }
        }
    },
    hideTipsDiv:function () {
        TREE_SHEET_HELPER.tipTimeStamp = +new Date();//这个是为了造价书清单编号树节点的那个延时显示而打的时间戳，防止已经要隐藏的提示框，延时显示
        let me = TREE_SHEET_HELPER;
        TREE_SHEET_HELPER.tipDiv = 'hide';
        if (me._toolTipElement) {
            $(me._toolTipElement).hide();
            me._toolTipElement = null;
        }
        TREE_SHEET_HELPER.tipDivCheck();//延时检查：当tips正在show的时候，就调用了hide方法，会导致tips一直存在，所以设置一个超时处理
    },
    tipDivCheck(){
        setTimeout(function () {
            let tips = $('#autoTip');
            if(TREE_SHEET_HELPER.tipDiv == 'show'){
                return;
            } else if(TREE_SHEET_HELPER.tipDiv == 'hide'&&tips){
                tips.hide();
                TREE_SHEET_HELPER._toolTipElement = null;
            }
        },600)
    },
    delayShowTips:function(hitinfo,setting,tips){//延时显示
        let delayTimes = 500; //延时时间
        let now_timeStamp = +new Date();
        TREE_SHEET_HELPER.tipTimeStamp = now_timeStamp;
        setTimeout(function () {
            if(now_timeStamp - TREE_SHEET_HELPER.tipTimeStamp == 0){//鼠标停下的时候才显示
                let tag = hitinfo.sheet.getTag(hitinfo.row, hitinfo.col);
                if(tips && tips !=""){ //有tips的话优先显示tips
                    tag = tips;
                }
                if(tag&&tag!=''){
                    TREE_SHEET_HELPER.showTipsDiv(tag,setting,hitinfo);
                }
            }
        },delayTimes);
    }
};