
function InitialControls() {
    loadSorting();
    loadFormatCells();
    loadcellMerging();
    loadDragDrop();
    loadFrozenCells();
    loadUndoRedo();
    loadFormulasSheet();
    loadCustomFunction();
    loadExcelIO();
};

// Cell Merging
var cellMergeSheet = {
    flexSheet: null,
    selectionFormatState: {
        isMergedCell: null
    },
    mergeBtn: null
};

function loadcellMerging() {
    var flexSheet;
    cellMergeSheet.flexSheet = <wijmo.grid.sheet.FlexSheet>wijmo.Control.getControl('#cellMergeSheet');
    cellMergeSheet.mergeBtn = <HTMLButtonElement> document.getElementById('cellMergeBtn');
    flexSheet = cellMergeSheet.flexSheet;
    if (flexSheet) {
        for (var colIdx = 0; colIdx < flexSheet.columns.length; colIdx++) {
            for (var rowIdx = 0; rowIdx < flexSheet.rows.length; rowIdx++) {
                flexSheet.setCellData(rowIdx, colIdx, colIdx + rowIdx);
            }
        }
        flexSheet.selectionChanged.addHandler(function () {
            cellMergeSheet.selectionFormatState = flexSheet.getSelectionFormatState();
            cellMergeUpdateBtnText();
        });
    }
};

function cellMergeUpdateBtnText() {

    var updateBtnText = cellMergeSheet.selectionFormatState.isMergedCell ? 'UnMerge' : 'Merge';
    cellMergeSheet.mergeBtn.innerText = cellMergeSheet.selectionFormatState.isMergedCell ? 'UnMerge' : 'Merge';
};

function mergeCells() {
    var flexSheet = cellMergeSheet.flexSheet;

    if (flexSheet) {
        flexSheet.mergeRange();
        cellMergeSheet.selectionFormatState = flexSheet.getSelectionFormatState();
        cellMergeUpdateBtnText();
    }
};

// Custom Function
var ctxcFunctionSheet = {
    flexSheet: null
};

function cFunctionSheet_unknownFunction(sender, e) {
    var result = '';
    if (e.params) {
        for (var i = 0; i < e.params.length; i++) {
            result += e.params[i];
        }
    }
    e.value = result;
};

function loadCustomFunction() {
    var flexSheet = ctxcFunctionSheet.flexSheet = <wijmo.grid.sheet.FlexSheet>wijmo.Control.getControl('#cFunctionSheet');

    flexSheet.addCustomFunction('customSumProduct', function (range1, range2) {
        var result = 0,
            val1, val2;

        if (range1.rowSpan === range2.rowSpan && range1.columnSpan === range2.columnSpan) {
            for (var rowIndex = 0; rowIndex < range1.rowSpan; rowIndex++) {
                for (var columnIndex = 0; columnIndex < range1.columnSpan; columnIndex++) {
                    val1 = +flexSheet.getCellValue(range1.topRow + rowIndex, range1.leftCol + columnIndex, false);
                    val2 = +flexSheet.getCellValue(range2.topRow + rowIndex, range2.leftCol + columnIndex, false);
                    result += val1 * val2;
                }
            }
        }
        return result;
    }, 'Custom SumProduct Function', 2, 2);

    for (var ri = 0; ri < flexSheet.rows.length; ri++) {
        for (var ci = 0; ci < 3; ci++) {
            flexSheet.setCellData(ri, ci, ri + ci);
        }
    }

    flexSheet.setCellData(0, 3, '=customSumProduct(A1:A10, B1:B10)');
    flexSheet.setCellData(1, 3, '=customFunc(1, "B", 3)');

};

// Drag & Drop
var ctxDragDrop = {
    flexSheet: null
};

function loadDragDrop() {
    var flexSheet;
    ctxDragDrop.flexSheet = <wijmo.grid.sheet.FlexSheet>wijmo.Control.getControl('#dragDropSheet');
    flexSheet = ctxDragDrop.flexSheet;
    if (flexSheet) {
        for (var colIdx = 0; colIdx < flexSheet.columns.length; colIdx++) {
            for (var rowIdx = 0; rowIdx < flexSheet.rows.length; rowIdx++) {
                flexSheet.setCellData(rowIdx, colIdx, colIdx + rowIdx);
            }
        }
        flexSheet.applyCellsStyle({ fontWeight: 'bold' }, [new wijmo.grid.CellRange(0, 0, 9, 0),
            new wijmo.grid.CellRange(10, 1, 19, 1)]);
        flexSheet.applyCellsStyle({ textDecoration: 'underline' }, [new wijmo.grid.CellRange(0, 2, 9, 2),
            new wijmo.grid.CellRange(10, 3, 19, 3)]);
        flexSheet.applyCellsStyle({ fontStyle: 'italic' }, [new wijmo.grid.CellRange(0, 4, 9, 4),
            new wijmo.grid.CellRange(10, 5, 19, 5)]);
        flexSheet.applyCellsStyle({ format: 'c2' }, [new wijmo.grid.CellRange(0, 0, 9, 7)]);
        flexSheet.applyCellsStyle({ backgroundColor: '#4488CC' }, [new wijmo.grid.CellRange(0, 0, 19, 0),
            new wijmo.grid.CellRange(0, 2, 19, 2), new wijmo.grid.CellRange(0, 4, 19, 4)]);
        flexSheet.applyCellsStyle({ color: '#CC8844' }, [new wijmo.grid.CellRange(0, 1, 19, 1),
            new wijmo.grid.CellRange(0, 3, 19, 3), new wijmo.grid.CellRange(0, 5, 19, 5)]);
        flexSheet.applyCellsStyle({ color: '#336699' }, [new wijmo.grid.CellRange(0, 6, 9, 7)]);
        flexSheet.applyCellsStyle({ backgroundColor: '#996633' }, [new wijmo.grid.CellRange(10, 6, 19, 7)]);
    }
};

// Excel I/O
var ctxcExcelIO = {
    fileName: '',
    flexSheet: null,
    fileNameInput: null,
    fileInput: null
};

function loadExcelIO() {
    var flexSheet;
    ctxcExcelIO.flexSheet = <wijmo.grid.sheet.FlexSheet>wijmo.Control.getControl('#excelIOSheet');
    ctxcExcelIO.fileNameInput = <HTMLInputElement>document.getElementById('fileName');
    ctxcExcelIO.fileInput = <HTMLInputElement>document.getElementById('importFile');
    flexSheet = ctxcExcelIO.flexSheet;
    if (flexSheet) {
        for (var sheetIdx = 0; sheetIdx < flexSheet.sheets.length; sheetIdx++) {
            flexSheet.selectedSheetIndex = sheetIdx;
            var sheetName = flexSheet.selectedSheet.name;
            if (sheetName === 'Unbound') {
                for (var colIdx = 0; colIdx < flexSheet.columns.length; colIdx++) {
                    for (var rowIdx = 0; rowIdx < flexSheet.rows.length; rowIdx++) {
                        flexSheet.setCellData(rowIdx, colIdx, colIdx + rowIdx);
                    }
                }
            } else {
                applyDataMap(flexSheet);
            }
        }
        flexSheet.selectedSheetIndex = 0;
    }
};

function excelIOLoad() {
    var flexSheet = ctxcExcelIO.flexSheet,
        fileInput = ctxcExcelIO.fileInput;
    if (flexSheet && fileInput.files[0]) {
        flexSheet.load(fileInput.files[0]);
    }
}

function excelIOSave() {
    var flexSheet = ctxcExcelIO.flexSheet,
        fileName;
    if (flexSheet) {
        if (!!ctxcExcelIO.fileName) {
            fileName = ctxcExcelIO.fileName;
        } else {
            fileName = 'FlexSheet.xlsx';
        }
        flexSheet.save(fileName);
    }
}

function fileNameChanged() {
    ctxcExcelIO.fileName = ctxcExcelIO.fileNameInput.value;
}

function applyDataMap(flexSheet) {
    var countries = ['US', 'Germany', 'UK', 'Japan', 'Italy', 'Greece'],
        products = ['Widget', 'Gadget', 'Doohickey'], column;
    // initialize the dataMap for the bound sheet.
    if (flexSheet) {
        column = flexSheet.columns.getColumn('Country');
        if (column && !column.dataMap) {
            column.dataMap = buildDataMap(countries);
        }
        column = flexSheet.columns.getColumn('Product');
        if (column && !column.dataMap) {
            column.dataMap = buildDataMap(products);
        }
    }
}

function buildDataMap(items) {
    var map = [];
    for (var i = 0; i < items.length; i++) {
        map.push({ key: i, value: items[i] });
    }
    return new wijmo.grid.DataMap(map, 'key', 'value');
}

// Format Cells
var applyFillColor = false,
    updatingSelection = false,
    formats = ['0', 'n2', 'p2', 'c2', '', 'd', 'D', 'f', 'F'],
    ctxFormatCells = {
        format: '',        
        flexSheet: null,
        cboFontName: null,
        cboFontSize: null,
        menuFormat:null,
        boldBtn: null,
        italicBtn: null,
        underlineBtn: null,
        leftBtn: null,
        centerBtn: null,
        rightBtn: null,
        colorPicker:null,
        sheetName: '',
        selectionFormatState: {
            isBold: null,
            isItalic: null,
            isUnderline: null,
            textAlign: null
        },
    };

function loadFormatCells() {
    initFlexSheet();
    initInputs();
};

function initInputs() {
    ctxFormatCells.cboFontName = <wijmo.input.ComboBox> wijmo.Control.getControl('#cboFontName');
    ctxFormatCells.cboFontSize = <wijmo.input.ComboBox>wijmo.Control.getControl('#cboFontSize');
    ctxFormatCells.menuFormat = <wijmo.input.Menu>wijmo.Control.getControl('#fcMenuFormat');
    initBtns();
    initColorPicker();
    setMenuHeader(ctxFormatCells.menuFormat);
}

function initBtns() {
    ctxFormatCells.boldBtn = wijmo.getElement('#boldBtn');
    ctxFormatCells.italicBtn = wijmo.getElement('#italicBtn');
    ctxFormatCells.underlineBtn = wijmo.getElement('#underlineBtn');
    ctxFormatCells.leftBtn = wijmo.getElement('#leftBtn');
    ctxFormatCells.centerBtn = wijmo.getElement('#centerBtn');
    ctxFormatCells.rightBtn = wijmo.getElement('#rightBtn');
}

function formatCellsUpdateBtns() {
    updateActiveState(ctxFormatCells.selectionFormatState.isBold, ctxFormatCells.boldBtn);
    updateActiveState(ctxFormatCells.selectionFormatState.isItalic, ctxFormatCells.italicBtn);
    updateActiveState(ctxFormatCells.selectionFormatState.isUnderline, ctxFormatCells.underlineBtn);
    updateActiveState(ctxFormatCells.selectionFormatState.textAlign === 'left', ctxFormatCells.leftBtn);
    updateActiveState(ctxFormatCells.selectionFormatState.textAlign === 'center', ctxFormatCells.centerBtn);
    updateActiveState(ctxFormatCells.selectionFormatState.textAlign === 'right', ctxFormatCells.rightBtn);
}

function updateActiveState(condition, btn) {
    condition ? addClass(btn, "active") : removeClass(btn, "active");
}

function initFlexSheet() {
    var sheetIdx,
        sheetName,
        colIdx,
        rowIdx,
        date,
        flexSheet;

    ctxFormatCells.flexSheet = <wijmo.grid.sheet.FlexSheet> wijmo.Control.getControl('#fcFlexSheet');
    flexSheet = ctxFormatCells.flexSheet;
    if (flexSheet) {
        flexSheet.selectionChanged.addHandler(function (sender, args) {
            updateSelection(args.range);
            ctxFormatCells.selectionFormatState = flexSheet.getSelectionFormatState();
        });

        for (sheetIdx = 0; sheetIdx < flexSheet.sheets.length; sheetIdx++) {
            flexSheet.selectedSheetIndex = sheetIdx;
            sheetName = flexSheet.selectedSheet.name;
            for (colIdx = 0; colIdx < flexSheet.columns.length; colIdx++) {
                for (rowIdx = 0; rowIdx < flexSheet.rows.length; rowIdx++) {
                    if (sheetName === 'Number') {
                        flexSheet.setCellData(rowIdx, colIdx, colIdx + rowIdx);
                    } else {
                        date = new Date(2015, colIdx, rowIdx + 1);
                        flexSheet.setCellData(rowIdx, colIdx, date);
                    }
                }
            }
        }
        flexSheet.selectedSheetIndex = 0;
        updateSelection(flexSheet.selection);
    }
};

// initialize the colorPicker control.
function initColorPicker() {
    var colorPicker = ctxFormatCells.colorPicker = <wijmo.input.ColorPicker>wijmo.Control.getControl('#fcColorPicker');
    var ua = window.navigator.userAgent,
        blurEvt;

    if (colorPicker) {
        // if the browser is firefox, we should bind the blur event.
        // if the browser is IE, we should bind the focusout event.
        blurEvt = /firefox/i.test(ua) ? 'blur' : 'focusout';
        // Hide the color picker control when it lost the focus.
        colorPicker.hostElement.addEventListener(blurEvt, function () {
            setTimeout(function () {
                if (!colorPicker.containsFocus()) {
                    applyFillColor = false;
                    colorPicker.hostElement.style.display = 'none';
                }
            }, 0);
        });

        // Initialize the value changed event handler for the color picker control.
        colorPicker.valueChanged.addHandler(function () {
            if (applyFillColor) {
                ctxFormatCells.flexSheet.applyCellsStyle({ backgroundColor: colorPicker.value });
            } else {
                ctxFormatCells.flexSheet.applyCellsStyle({ color: colorPicker.value });
            }
        });
    }
}

function fcMenuFormat_Changed(sender) {
    var flexSheet = ctxFormatCells.flexSheet,
        menu = sender;
    if (menu.selectedValue) {
        ctxFormatCells.format = menu.selectedValue.CommandParameter;
        setMenuHeader(menu);
        if (flexSheet && !updatingSelection) {
            flexSheet.applyCellsStyle({ format: ctxFormatCells.format });
        }
    }
}

function setMenuHeader(menu) {
    menu.header = "Format:<b>" + menu.selectedValue === null ? "" : menu.selectedValue.Header + "</b>";
}

function fontChanged(sender) {
    if (!updatingSelection && ctxFormatCells.flexSheet) {
        ctxFormatCells.flexSheet.applyCellsStyle({ fontFamily: ctxFormatCells.cboFontName.selectedItem.Value });
    }
}

function fontSizeChanged(sender) {
    if (!updatingSelection && ctxFormatCells.flexSheet) {
        ctxFormatCells.flexSheet.applyCellsStyle({ fontSize: ctxFormatCells.cboFontSize.selectedItem.Value });
    }
}

// apply the text alignment for the selected cells
function applyCellTextAlign(textAlign) {
    ctxFormatCells.flexSheet.applyCellsStyle({ textAlign: textAlign });
    ctxFormatCells.selectionFormatState.textAlign = textAlign;
    formatCellsUpdateBtns();
};

// apply the bold font weight for the selected cells
function applyBoldStyle() {
    ctxFormatCells.flexSheet.applyCellsStyle({ fontWeight: ctxFormatCells.selectionFormatState.isBold ? 'none' : 'bold' });
    ctxFormatCells.selectionFormatState.isBold = !ctxFormatCells.selectionFormatState.isBold;
    formatCellsUpdateBtns();
};

// apply the underline text decoration for the selected cells
function applyUnderlineStyle() {
    ctxFormatCells.flexSheet.applyCellsStyle({ textDecoration: ctxFormatCells.selectionFormatState.isUnderline ? 'none' : 'underline' });
    ctxFormatCells.selectionFormatState.isUnderline = !ctxFormatCells.selectionFormatState.isUnderline;
    formatCellsUpdateBtns();
};

// apply the italic font style for the selected cells
function applyItalicStyle() {
    ctxFormatCells.flexSheet.applyCellsStyle({ fontStyle: ctxFormatCells.selectionFormatState.isItalic ? 'none' : 'italic' });
    ctxFormatCells.selectionFormatState.isItalic = !ctxFormatCells.selectionFormatState.isItalic;
    formatCellsUpdateBtns();
};

// show the color picker control.
function showColorPicker(e, isFillColor) {
    var colorPicker = ctxFormatCells.colorPicker,
        offset = cumulativeOffset(e.target);

    if (colorPicker) {
        colorPicker.hostElement.style.display = 'inline';
        colorPicker.hostElement.style.left = offset.left + 'px';
        colorPicker.hostElement.style.top = (offset.top - colorPicker.hostElement.clientHeight - 5) + 'px';
        colorPicker.hostElement.focus();
    }

    applyFillColor = isFillColor;
};

// Update the selection object of the scope.
function updateSelection(sel) {
    var flexSheet = ctxFormatCells.flexSheet,
        row = flexSheet.rows[sel.row],
        rowCnt = flexSheet.rows.length,
        colCnt = flexSheet.columns.length,
        r,
        c,
        cellStyle,
        cellContent,
        cellFormat;

    updatingSelection = true;
    if (ctxFormatCells.cboFontName && sel.row > -1 && sel.col > -1 && rowCnt > 0 && colCnt > 0
        && sel.col < colCnt && sel.col2 < colCnt
        && sel.row < rowCnt && sel.row2 < rowCnt) {
        r = sel.row >= rowCnt ? rowCnt - 1 : sel.row;
        c = sel.col >= colCnt ? colCnt - 1 : sel.col;
        cellContent = flexSheet.getCellData(sel.row, sel.col);
        cellStyle = flexSheet.selectedSheet.getCellStyle(sel.row, sel.col);
        if (cellStyle) {
            ctxFormatCells.cboFontName.selectedIndex = checkFontfamily(cellStyle.fontFamily);
            ctxFormatCells.cboFontSize.selectedIndex = checkFontSize(cellStyle.fontSize);
            cellFormat = cellStyle.format;
        } else {
            ctxFormatCells.cboFontName.selectedIndex = 0;
            ctxFormatCells.cboFontSize.selectedIndex = 5;
        }

        if (!!cellFormat) {
            ctxFormatCells.format = cellFormat;
        } else {
            if (wijmo.isInt(cellContent)) {
                ctxFormatCells.format = '0';
            } else if (wijmo.isNumber(cellContent)) {
                ctxFormatCells.format = 'n2';
            } else if (wijmo.isDate(cellContent)) {
                ctxFormatCells.format = 'd';
            }
        }
        ctxFormatCells.selectionFormatState = flexSheet.getSelectionFormatState()
        ctxFormatCells.menuFormat.selectedIndex = formats.indexOf(ctxFormatCells.format);
        formatCellsUpdateBtns();
    }
    updatingSelection = false;
};

// check font family for the font name combobox of the ribbon.
function checkFontfamily(fontFamily) {
    var fonts = ctxFormatCells.cboFontName.itemsSource.items,
        fontIndex = 0,
        font;

    if (!fontFamily) {
        return fontIndex;
    }

    for (; fontIndex < fonts.length; fontIndex++) {
        font = fonts[fontIndex];

        if (font.Name === fontFamily || font.Value === fontFamily) {
            return fontIndex;
        }
    }

    return 0;
}

// check font size for the font size combobox of the ribbon.
function checkFontSize(fontSize) {
    var sizeList = ctxFormatCells.cboFontSize.itemsSource.items,
        index = 0,
        size;

    if (fontSize == undefined) {
        return 5;
    }

    for (; index < sizeList.length; index++) {
        size = sizeList[index];

        if (size.Value === fontSize || size.Name === fontSize) {
            return index;
        }
    }

    return 5;
}

// Get the absolute position of the dom element.
function cumulativeOffset(element) {
    var top = 0, left = 0, scrollTop = 0, scrollLeft = 0;

    do {
        top += element.offsetTop || 0;
        left += element.offsetLeft || 0;
        scrollTop += element.scrollTop || 0;
        scrollLeft += element.scrollLeft || 0;
        element = element.offsetParent;
    } while (element && !(element instanceof HTMLBodyElement));

    scrollTop += document.body.scrollTop || document.documentElement.scrollTop;
    scrollLeft += document.body.scrollLeft || document.documentElement.scrollLeft;

    return {
        top: top - scrollTop,
        left: left - scrollLeft
    };
};

function hasClass(obj, cls) {
    return obj && obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}

function addClass(obj, cls) {
    if (!this.hasClass(obj, cls)) obj.className += " " + cls;
}

function removeClass(obj, cls) {
    if (hasClass(obj, cls)) {
        var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
        obj.className = obj.className.replace(reg, ' ');
    }
}

// Formulas
var ctxFormulas = {
    flexSheet: null,
    currentCellData: null
};

function loadFormulasSheet() {
    ctxFormulas.flexSheet = <wijmo.grid.sheet.FlexSheet> wijmo.Control.getControl('#formulaSheet');
    var flexSheet = ctxFormulas.flexSheet;
    flexSheet.selectionChanged.addHandler(function (sender, args) {
        var selection = args.range;
        if (selection.isValid) {
            ctxFormulas.currentCellData = ctxFormulas.flexSheet.getCellData(selection.row, selection.col, true);
            document.getElementById('dvCurrentCellData').innerText = ctxFormulas.currentCellData;
        }
    });
    flexSheet.deferUpdate(function () {
        generateExpenceReport(flexSheet);
    });
};

// Set content for the use case template sheet.
function generateExpenceReport(flexSheet) {
    flexSheet.setCellData(1, 1, 'Expense Report');
    flexSheet.setCellData(3, 1, 'Date');
    flexSheet.setCellData(3, 2, 'Fuel');
    flexSheet.setCellData(3, 3, 'Parking(per hour)');
    flexSheet.setCellData(3, 4, 'Parking(hours)');
    flexSheet.setCellData(3, 5, 'Total');;
    flexSheet.setCellData(9, 1, 'Total');
    flexSheet.setCellData(10, 4, 'Subtotal');
    flexSheet.setCellData(11, 4, 'Cash Advances');
    flexSheet.setCellData(12, 4, 'Total');

    setExpenseData(flexSheet);

    applyStyleForExpenceReport(flexSheet);
}

// set expense detail data for the use case template sheet.
function setExpenseData(flexSheet) {
    var rowIndex,
        colIndex,
        value;

    for (rowIndex = 4; rowIndex <= 8; rowIndex++) {
        for (colIndex = 2; colIndex <= 5; colIndex++) {
            if (colIndex === 5) {
                flexSheet.setCellData(rowIndex, colIndex, '=C' + (rowIndex + 1) + ' + Product(C' + (rowIndex + 1) + ':D' + (rowIndex + 1) + ')');
            } else if (colIndex === 4) {
                value = parseInt((7 * Math.random()).toString()) + 1;
                flexSheet.setCellData(rowIndex, colIndex, value);
            } else if (colIndex === 3) {
                flexSheet.setCellData(rowIndex, colIndex, 3.75);
            } else {
                value = 200 * Math.random();
                flexSheet.setCellData(rowIndex, colIndex, value);
            }
        }
    }

    flexSheet.setCellData(4, 1, '2015-3-1');
    flexSheet.setCellData(5, 1, '2015-3-3');
    flexSheet.setCellData(6, 1, '2015-3-7');
    flexSheet.setCellData(7, 1, '2015-3-11');
    flexSheet.setCellData(8, 1, '2015-3-18');
    flexSheet.setCellData(9, 2, '=Sum(C5:C9)');
    flexSheet.setCellData(9, 4, '=Sum(Product(D5:E5), Product(D6:E6), Product(D7:E7), Product(D8:E8), Product(D9:E9))');
    flexSheet.setCellData(9, 5, '=Sum(F5:F9)');
    flexSheet.setCellData(10, 5, '=F13-F12');
    flexSheet.setCellData(11, 5, 800);
    flexSheet.setCellData(12, 5, '=F10');
}

// Apply styles for the use case template sheet.
function applyStyleForExpenceReport(flexSheet) {
    flexSheet.columns[0].width = 10;
    flexSheet.columns[1].width = 90;
    flexSheet.columns[2].width = 80;
    flexSheet.columns[3].width = 140;
    flexSheet.columns[4].width = 120;
    flexSheet.columns[5].width = 80;
    for (var i = 2; i <= 3; i++) {
        flexSheet.columns[i].format = 'c2';
    }
    flexSheet.columns[5].format = 'c2';
    flexSheet.rows[1].height = 45;
    flexSheet.applyCellsStyle({
        fontSize: '24px',
        fontWeight: 'bold',
        color: '#696964'
    }, [new wijmo.grid.CellRange(1, 1, 1, 3)]);
    flexSheet.mergeRange(new wijmo.grid.CellRange(1, 1, 1, 3));
    flexSheet.applyCellsStyle({
        fontWeight: 'bold',
        backgroundColor: '#FAD9CD',
    }, [new wijmo.grid.CellRange(3, 1, 3, 5),
            new wijmo.grid.CellRange(9, 1, 9, 5)]);
    flexSheet.applyCellsStyle({
        textAlign: 'center'
    }, [new wijmo.grid.CellRange(3, 1, 3, 5)]);
    flexSheet.applyCellsStyle({
        format: 'c2'
    }, [new wijmo.grid.CellRange(9, 4, 9, 4)]);
    flexSheet.applyCellsStyle({
        backgroundColor: '#F4B19B'
    }, [new wijmo.grid.CellRange(4, 1, 8, 5)]);
    flexSheet.applyCellsStyle({
        fontWeight: 'bold',
        textAlign: 'right'
    }, [new wijmo.grid.CellRange(10, 4, 12, 4)]);
}

// Frozen Cells
var ctxfrozenCells = {
    flexSheet: null,
    isFrozen: false,
    frozenBtn: null,
    mergeBtn:null
};

function loadFrozenCells() {
    var flexSheet;
    ctxfrozenCells.flexSheet = <wijmo.grid.sheet.FlexSheet>wijmo.Control.getControl('#frozenSheet');
    ctxfrozenCells.mergeBtn = wijmo.getElement('#frozenBtn');
    flexSheet = ctxfrozenCells.flexSheet;
    if (flexSheet) {
        for (var colIdx = 0; colIdx < flexSheet.columns.length; colIdx++) {
            for (var rowIdx = 0; rowIdx < flexSheet.rows.length; rowIdx++) {
                flexSheet.setCellData(rowIdx, colIdx, colIdx + rowIdx);
            }
        }
    }
};

function frozenCellsUpdateBtn() {
    ctxfrozenCells.mergeBtn.innerText = ctxfrozenCells.isFrozen ? 'UnFreeze' : 'Freeze';
}

function freezeCells() {
    var flexSheet = ctxfrozenCells.flexSheet;
    if (flexSheet) {
        flexSheet.freezeAtCursor();
        frozenSheet_updateFrozenState();
    }
}

function frozenSheet_updateFrozenState() {
    var flexSheet = ctxfrozenCells.flexSheet;
    if (flexSheet) {
        if (ctxfrozenCells.flexSheet.frozenColumns > 0 || ctxfrozenCells.flexSheet.frozenRows > 0) {
            ctxfrozenCells.isFrozen = true;
        } else {
            ctxfrozenCells.isFrozen = false;
        }

        frozenCellsUpdateBtn();
    }
}

// Sorting
var ctxSorting = {
    flexSheet: null,
    sortManager: null,
    moveup: null,
    movedown: null,
    tbody: null,
    columns: null
};

function loadSorting() {
    ctxSorting.flexSheet = <wijmo.grid.sheet.FlexSheet>wijmo.Control.getControl('#sortingFlexSheet');
    ctxSorting.sortManager = ctxSorting.flexSheet.sortManager;
    ctxSorting.moveup = <HTMLButtonElement>document.getElementById('moveup');
    ctxSorting.movedown = <HTMLButtonElement>document.getElementById('movedown');
    ctxSorting.tbody = wijmo.getElement('#sortTable tbody');
    ctxSorting.columns = getColumns();
    ctxSorting.flexSheet.selectedSheetChanged.addHandler(function (sender, args) {
        ctxSorting.columns = getColumns();
        ctxSorting.sortManager = ctxSorting.flexSheet.sortManager;
        updateSortTable();
    });
    updateSortTable();
    applyDataMap(ctxSorting.flexSheet);
};

function changeBtnState() {
    ctxSorting.moveup.disabled = ctxSorting.sortManager.sortDescriptions.currentPosition <= 0;
    ctxSorting.movedown.disabled = ctxSorting.sortManager.sortDescriptions.currentPosition >= ctxSorting.sortManager.sortDescriptions.itemCount - 1;
}

function updateSortTable() {
    var i, j, html = '', tr, sortDescriptions = ctxSorting.sortManager.sortDescriptions,
        items = sortDescriptions.items;
    for (i = 0; i < items.length; i++) {
        tr = '<tr onclick="moveCurrentTo(' + i + ')" ' +
            (sortDescriptions.currentItem == items[i] ? 'class="success"' : '') + '>' +
            '<td>' +
            '<select class="form-control" onchange="columnIndexChanged(this, ' + i + ')">' +
            '<option value=-1></option>';

        for (j = 0; j < ctxSorting.columns.length; j++) {
            tr += '<option value="' + j + '" ' + (j == items[i].columnIndex ? 'selected="selected"' : '') +
                '>' + ctxSorting.columns[j] + '</option>';
        }

        tr += '</select></td>' +
            '<td>' +
            '<select class="form-control" onchange="ascendingChanged(this, ' + i + ')">' +
            '<option value="0" ' + (items[i].ascending ? 'selected="selected"' : '') + '>Ascending</option>' +
            '<option value="1" ' + (!items[i].ascending ? 'selected="selected"' : '') + '>Descending</option>' +
            '</select></td></tr>';
        html += tr;
    }
    ctxSorting.tbody.innerHTML = html;
    changeBtnState();
}

function moveCurrentTo(index) {
    var items = ctxSorting.sortManager.sortDescriptions.items, i = 0;
    ctxSorting.sortManager.sortDescriptions.moveCurrentTo(items[index]);
    for (; i < ctxSorting.tbody.children.length; i++) {
        ctxSorting.tbody.children[i].className = index == i ? 'success' : '';
    }
    changeBtnState();
}

function columnIndexChanged(ele, index) {
    if (ctxSorting.sortManager.sortDescriptions.items[index] != null)
        ctxSorting.sortManager.sortDescriptions.items[index].columnIndex = +ele.value;
}

function ascendingChanged(ele, index) {
    ctxSorting.sortManager.sortDescriptions.items[index].ascending = ele.value == "0";
}

// commit the sorts
function commitSort() {
    ctxSorting.sortManager.commitSort();
};

// cancel the sorts
function cancelSort() {
    ctxSorting.sortManager.cancelSort();
};

// add new sort level
function addSortLevel() {
    ctxSorting.sortManager.addSortLevel();
    updateSortTable();
};

// delete current sort level
function deleteSortLevel() {
    ctxSorting.sortManager.deleteSortLevel();
    updateSortTable();
};

// copy a new sort level by current sort level setting.
function copySortLevel() {
    ctxSorting.sortManager.copySortLevel();
    updateSortTable();
};

// move the sort level
function moveSortLevel(offset) {
    ctxSorting.sortManager.moveSortLevel(offset);
    updateSortTable();
};
// get the columns with the column header text for the column selection for sort setting.
function getColumns() {
    var columns = [],
        flex = ctxSorting.flexSheet,
        i = 0;

    if (flex) {
        for (; i < flex.columns.length; i++) {
            columns.push('Column ' + wijmo.grid.sheet.FlexSheet.convertNumberToAlpha(i));
        }
    }

    return columns;
}


// Undo/Redo
var ctxuredoSheet = {
    flexSheet: null,
    undoStack: null
};


function loadUndoRedo() {
    var flexSheet;
    ctxuredoSheet.flexSheet = <wijmo.grid.sheet.FlexSheet>wijmo.Control.getControl('#uredoSheet');
    flexSheet = ctxuredoSheet.flexSheet;
    flexSheet.deferUpdate(function () {
        var colIdx,
            rowIdx;

        ctxuredoSheet.undoStack = flexSheet.undoStack;
        // initialize the dataMap for the bound sheet.
        if (flexSheet) {
            for (colIdx = 0; colIdx < flexSheet.columns.length; colIdx++) {
                for (rowIdx = 0; rowIdx < flexSheet.rows.length; rowIdx++) {
                    flexSheet.setCellData(rowIdx, colIdx, colIdx + rowIdx);
                }
            }
        }
    });
};

// Excutes undo command.
function undoFunc() {
    if (ctxuredoSheet.flexSheet)
        ctxuredoSheet.flexSheet.undo();
};

// Excutes redo command.
function redoFunc() {
    if (ctxuredoSheet.flexSheet)
        ctxuredoSheet.flexSheet.redo();
};


