/// class PD.Web.UI.Controls.Grid
/// using PD.Web.UI.Controls.Control

PD.Web.UI.Controls.GridSelectionMode = {
    none: "none",
    single: "single",
    multiple: "multiple"
}

PD.Web.UI.Controls.Grid =
PD.Web.UI.Controls.Control.extend({

    //===================================
    // FIELDS
    //===================================

    _configuration: null,
    _dataSource: null,
    _modules: null,

    //===================================
    // CONSTRUCTOR
    //===================================

    init: function (options) {
        this._super($.extend(true, this.getDefaultOptions(), options));
    },

    //===================================
    // PROPERTIES
    //==================================

    get_options: function () {
        return this._options;
    },

    get_kendo: function () {
        return this.get_node().data("kendoGrid");
    },

    get_configuration: function () {
        return this._configuration;
    },

    get_dataSource: function () {
        return this._dataSource;
    },

    //===================================
    // EVENT HANDLERS
    //===================================

    template: function (e) {
        return "<div class='-pd-viewgrid'></div>";
    },

    onActivate: function (e) {
        this._initConfiguration();
        this.get_node().attr("uid", this.get_uid());
    },

    //===================================
    // PUBLIC METHODS
    //===================================

    destroy: function () {
        this.unloadModules();
        if (this.get_kendo() != null) {
            this.get_kendo().destroy();
        }
        this.remove();
    },

    build: function () {
        this._initConfiguration();
    },

    redraw: function () {
        if (this.get_kendo()) {
            this.get_kendo().refresh();
        }
    },

    refresh: function (options) {

        /*
        TODO: need to figure out a way to do this consistently with one method  
        instead of switching based upon the existence of the selection module.
        */

        var selectionModule = this.modules("selection");
        if (selectionModule) {
            selectionModule.refresh(options);
        }
        else {
            if (this.get_dataSource() != null) {
                this.get_dataSource().read();
            }
        }
    },
 
    modules: function (id) {

        if (this._modules == null) {
            this._modules = new PD.Web.UI.Controls.GridModuleCollection();
        }

        if (id !== undefined) {
            return this._modules.get(id);
        }

        return this._modules;

    },

    getSelection: function () {
        return this.modules("selection") ? this.modules("selection").getSelectedItem() : null;
    },

    getSelections: function () {

        var result = null,
            pk = this.get_options()["pk"];

        if (this.modules("selection")) {
            result = this.modules("selection").getSelections();
        }

        return result || new PD.Web.UI.Controls.GridSelection(pk);

    },

    getOption: function (path, defaultValue) {

        var result = undefined,
            base = this.get_options(),
            items = new PD.BCL.List(path.split(".")),
            lastIndex = items.count() - 1;

        items.each(function (index, item) {
            if (base[item] !== undefined) {
                base = base[item]
                if (index === lastIndex) {
                    result = base;
                }
            }
            else {
                return false;
            }
        });

        if (result === undefined) {
            result = defaultValue;
        }

        return result;

    },

    loadConfiguration: function () {
        return new PD.Web.UI.Controls.GridConfiguration();
    },

    loadDataSource: function () {
        return new PD.Web.UI.Controls.GridDataSource();
    },

    getDefaultOptions: function () {
        return {
            autoBind: false,
            pageable: true,
            height: "100%"
        };
    },

    remove: function () {
        this._super();
        this.unloadModules();
    },

    //===================================
    // PRIVATE METHODS
    //===================================

    _initConfiguration: function (args) {
        var that = this;
        this._configuration = this.loadConfiguration();
        if (this._configuration != null) {
            this._configuration.execute(this, function (configuration) {
                that.getOption("built", () => { })();
                that._initDataSource(configuration);
            });
        }
    },

    _initDataSource: function (configuration) {

        var that = this,
            readyFn = this.get_options()["ready"];

        this._dataSource = this.loadDataSource();

        if (this._dataSource != null) {
            this._dataSource.execute(this, function (dataSource) {
                that._initGrid(configuration, dataSource);
            });
        }
        
        if (PD.Type.isFunction(readyFn)) {
            readyFn(this);
        }

    },

    _initGrid: function (configuration, dataSource) {

        let dataBoundCallback = this.getOption("dataBound", () => { });

        if (this.get_kendo() !== undefined) {
            this.get_kendo().destroy();
        };

        this.get_node().empty();
        this.get_node().kendoGrid({});
        
        this._initModules();

        this.get_options().dataSource = dataSource.get_instance()

        this.get_kendo().setOptions(this.get_options());

        this._startModules();

        this.get_kendo().dataSource.read();

        this.get_kendo().bind("dataBound", dataBoundCallback);

    },

    _initModules: function () {

        var that = this;

        this.modules().each(function (index, module) {
            module.stop();
        });

        this.modules().clear();

        if (this.modules().count() === 0) {
            this.addDefaultModules(this.modules());
            this.addModules(this.modules());
            this.addOptionModules(this.modules());
        }

        this.modules().each(function (index, module) {
            module.activate(that);
            var options = module.getOptionSettings();
            if (options != null) {
                that.get_kendo().setOptions(options);
            }
        });

    },

    _startModules: function () {

        this.modules().each(function (index, module) {
            if (module.meetsLoadConditions()) {
                module.start();
            }
        });

        this.modules().each(function (index, module) {
            if (module.meetsLoadConditions()) {
                module.ready();
            }
        });

    },

    addDefaultModules: function (modules) {

        var NS = PD.Web.UI.Controls;

        if (this.getOption("selectionMode") != "none") {
            modules.add(new NS.GridSelectionModule());
        }

        modules.add(new NS.GridHeaderModule());
        modules.add(new NS.GridFooterModule());
        modules.add(new NS.GridColumnNoResizeModule());
        modules.add(new NS.GridRowContextMenuModule());
        modules.add(new NS.GridMessagingModule());

    },

    addModules: function (modules) {

        var NS = PD.Web.UI.Controls;

        modules.add(new NS.GridMessageModule());

    },

    unloadModules: function (modules) {

        this.modules().each(function (index, module) {
            module.unload();
        });

    },

    addOptionModules: function (modules) {

        var optionModules = new PD.BCL.List(this.get_options()["modules"]);

        optionModules.each(function (index, name) {
            var type = PD.Type.getType(name);
            if (type != null) {
                modules.add(new type());
            }
        });

    },

    getRowData: function ($element) {

        var result = null;
        var $row = $element.closest("tr[role=row][data-uid]");

        if ($element != null && $element.length > 0 && $row.length > 0) {
            result = this.get_kendo().dataItem($row);
        }

        return result;

    }

});