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

var TREE_SHEET_HELPER = {
    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;
        return style;
    },
    loadSheetHeader: function (setting, sheet) {
        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(col.head.wordWrap);
                }
                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) {
                    cell.value(colSetting.data.getText(node));
                } else {
                    cell.value(getFieldText2());
                }
            });
            sheet.autoFitRow(node.serialNo());
            if (recursive) {
                TREE_SHEET_HELPER.refreshTreeNodeData(setting, sheet, node.children, recursive);
            }
        });
    },
    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) {
            // ������(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;
            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();
            }
        };

        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));
            });
            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);
        });
    }
};
