define(
    [
        'scripts/knockout-3.3.0',
        'scripts/ACTComponent.js',
        'jqx/jqxcore',
        'jqx/jqxdata',
        'jqx/jqxbuttons',
        'jqx/jqxscrollbar',
        'jqx/jqxdatatable',
        'jqx/jqxtreegrid',
    ],
    function(ko, ACTComponent) {

        function TreeGridComponentViewModel(params, element) {

            var _this = this;
            _this.base = new ACTComponent($(element), params);
            _this.element = element;
            _this.params = params;
            var $treeGrid = $(element).find('#treeGrid');
            // this.ItemSelected = params.Model.ItemSelected;

            // var $treeGrid = $(element).find('#jqxTreeGrid');

            _this.OnCellChanged = params.Model.OnCellChanged;
            _this.OnRowChecked = params.Model.OnRowChecked;
            _this.OnRowUnChecked = params.Model.OnRowUnChecked;
            _this.OnRowDoubleClicked = params.Model.OnRowDoubleClicked;
            _this.base.addCallbackX(_this, "onCellChanged", "OnCellChanged");
            _this.base.addCallback1(_this, "onRowChecked", "OnRowChecked");
            _this.base.addCallback1(_this, "onRowUnChecked", "OnRowUnChecked");
            _this.base.addCallback1(_this, "onRowDoubleClicked", "OnRowDoubleClicked");

            _this.base.onMessage = function(name, obj) {
                // ! list need .$values
                switch (name) {
                    case "IsEditable":
                    $treeGrid.jqxTreeGrid({ editable:obj }); 
                        break;
                case "LockRow":
                    for(var treeGridRow in obj.$values){
                        $treeGrid.jqxTreeGrid({ 'lockRow': treeGridRow.ID }); 
                    }
                    break;
                }
            };

            _this.base.onRefresh = function(obj) {

                _this.treeGridModel = obj.TreeGridModel;
                _this.treeGridRows = _this.treeGridModel.Root.Children;
                _this.isEditable = obj.IsEditable;

                _this.dataFields = [];
                _this.dataFields.push({
                    'name': 'Children',
                    'type': 'array'
                }, {
                    'name': 'ID',
                    'type': 'number'
                });

                // Format columns to assign the right data.
                var headers = _this.treeGridModel.Headers;
                _this.columns = [];
                for (var i = 0; i < headers.length; i++) {
                    var column = {};
                    column['text'] = headers[i].text;
                    column['dataField'] = "column" + i;
                    // column['width'] = (100 / headers.length).toString() + "%";
                    _this.columns.push(column);
                    _this.dataFields.push({
                        'name': "column" + i,
                        'type': 'string'
                    });
                }

                var translateData = function(treeGridRows) {
                    for (var itemIndex = 0; itemIndex < treeGridRows.length; itemIndex++) {
                        var currentItem = treeGridRows[itemIndex];
                        var columns = currentItem.Columns.$values;
                        for (var columnIndex = 0; columnIndex < columns.length; columnIndex++) {
                            var columnValue = columns[columnIndex];
                            var dataName = "column" + columnIndex;
                            currentItem[dataName] = columnValue || "";
                        }
                        if (currentItem.Children.length > 0) {
                            translateData(currentItem.Children);
                        }
                    }
                };
                translateData(_this.treeGridRows);

                _this.lockRows =  function(){
                    var treeItemQueue = _this.treeGridRows.slice();
                    while(treeItemQueue.length > 0){
                        var itemRow = treeItemQueue.pop();
                        if(itemRow.IsLocked){
                            $treeGrid.jqxTreeGrid('lockRow', itemRow.ID);
                        }
                        if(itemRow.Children.length > 0){
                            treeItemQueue = treeItemQueue.concat(itemRow.Children);
                        }
                    }
                };

                // prepare the data
                var source = {
                    dataType: "json",
                    dataFields: _this.dataFields,
                    hierarchy: {
                        root: 'Children'
                    },
                    id: 'ID',
                    localData: _this.treeGridRows
                };
                var dataAdapter = new $.jqx.dataAdapter(source);
                // create Tree Grid
                $treeGrid.jqxTreeGrid({
                    source: dataAdapter,
                    // sortable: true,
                    editable: _this.isEditable,
                    editSettings: {
                        saveOnBlur: true,
                        saveOnSelectionChange: true,
                        cancelOnEsc: true,
                        saveOnEnter: true,
                        editSingleCell: true,
                        editOnDoubleClick: true
                    },
                    columns: _this.columns,
                    columnsResize: true,
                    width: "99.5%",
                    height: "99.6%",
                    // checkboxes: true
                });

                _this.params.ready(true);
                _this.resizeColumns();
                _this.lockRows();
            };

            $treeGrid.on('cellEndEdit', function(event) {
                var args = event.args;
                var itemId = args.key;
                var rowData = args.row;
                var columnIndex = parseInt(args.dataField.substr("column".length));
                var value = args.value;
                _this.onCellChanged(itemId, columnIndex, value);
            });

            $treeGrid.on('rowUncheck', function(event) {
                var args = event.args;
                var itemId = args.key;
                _this.onRowUnChecked(itemId);
            });

            $treeGrid.on('rowCheck', function(event) {
                var args = event.args;
                var itemId = args.key;
                _this.onRowChecked(itemId);
            });

            $treeGrid.on('rowDoubleClick', function(event) {
                var args = event.args;
                var itemId = args.key;
                _this.onRowDoubleClicked(itemId);
            });

            _this.resizeColumns = function() {
                var treeGridWidth = $treeGrid.width();
                var columnCount = _this.columns.length;
                var width = (treeGridWidth / columnCount);
                for (var i = 0; i < columnCount; i++) {
                    $treeGrid.jqxTreeGrid('setColumnProperty', 'column' + i, 'width', width);
                }
            };

            params.baseModel.resizeFunctions[params.baseModel.resizeFunctions.length] = function(height, width) {
                $treeGrid.jqxTreeGrid('width', "99.5%");
                $treeGrid.jqxTreeGrid('height', "99.6%");
                _this.resizeColumns();
            };
            _this.base.initialize();
        }

        return {
            createViewModel: function(params, componentInfo) {
                return new TreeGridComponentViewModel(params, componentInfo.element);
            }
        };
    });
