/// class ProspectDirector.Web.UI.Utilities.Kendo.GridSelection

ProspectDirector.Web.UI.Utilities.Kendo.GridSelection = Class.extend({

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

    CSS_SELECTED: "k-state-selected",
    QRY_SELECTED: ".k-state-selected",
    QRY_ROW: "TR[data-uid]",
    QRY_ROWS: ".k-grid-content TR[data-uid]",

    _grid: null,
    _selections: null,
    _options: null,

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

    init: function (options) {

        this._options = $.extend(true, {
            grid: null,
            primaryKey: "ObjectId",
            selection: {
                mode: "single",
                onRightClick: false
            },
            click: null,
            dblclick: null,
            mousedown: null,
            change: null,
            message: null
        }, options);

        this._init_manager();

    },

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

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

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

    get_gridDomNode: function () {
        return this.get_grid().element;
    },

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

    get_selections: function () {
        return this._selections;
    },

    //==============================
    // INITIALIZERS
    //==============================

    _init_manager: function () {

        this.get_gridDomNode().css({
            cursor: "default"
        });

        this.get_gridDomNode().disableTextSelection();

        //TODO: Determine a method for preventing kendo grid selections post initialization.
        //this.get_grid().options.selectable = false;

        this._selections = new ProspectDirector.Web.UI.Utilities.Kendo.GridSelectionCollection({
            grid: this.get_grid(),
            primaryKey: this.get_options().primaryKey
        });

        /* UNBIND EXISTING EVENT HANDLERS */
        this.get_grid().unbind("change");
        this.get_grid().unbind("dataBound");
        this.get_gridDomNode().off("click.SelectionManager");
        this.get_gridDomNode().off("dblclick.SelectionManager");
        this.get_gridDomNode().off("mousedown.SelectionManager");

        /* BIND EVENT HANDLERS */
        this.get_grid().bind("change", $.proxy(this._grid_onChange, this));
        this.get_grid().bind("dataBound", $.proxy(this._grid_onDataBound, this));
        this.get_gridDomNode().on("click.SelectionManager", this.QRY_ROWS, $.proxy(this._row_onClick, this));
        this.get_gridDomNode().on("dblclick.SelectionManager", this.QRY_ROWS, $.proxy(this._row_onDblClick, this));
        this.get_gridDomNode().on("mousedown.SelectionManager", this.QRY_ROWS, $.proxy(this._row_onMouseDown, this));

        /* BIND EXTERNAL EVENT HANDLERS */
        if ($.isFunction(this.get_options().click)) {
            $(this).bind("click", this.get_options().click);
        }

        if ($.isFunction(this.get_options().dblclick)) {
            $(this).bind("dblclick", this.get_options().dblclick);
        }

        if ($.isFunction(this.get_options().mousedown)) {
            $(this).bind("mousedown", this.get_options().mousedown);
        }

        if ($.isFunction(this.get_options().change)) {
            $(this).bind("change", this.get_options().change);
        }

    },

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

    _grid_onChange: function (e) {
        e.preventDefault(e);
    },

    _grid_onDataBound: function (e) {

        this._restore();

        if ($.isFunction(this.get_options().message)) {
            this.get_options().message(this, {
                recordCount: this.get_dataSource().data().length
            });
        }
        else {
            this._setDefaultMessage();
        }

    },

    _row_onClick: function (e) {

        var row = $(e.target).closest(this.QRY_ROW),
            rowData = this._getRowData(row),
            isRowSelected = row.hasClass(this.CSS_SELECTED),
            isMultiSelect = e.ctrlKey,
            isMultiSelectEnabled = this.get_options().selection.mode === "multiple",
            isMutliSelection = this.get_selections().count() > 1;

        if (!isMultiSelect || !isMultiSelectEnabled) {

            if (isRowSelected && !isMutliSelection) {
                this._clear();
            }
            else {
                this.clear();
            }

            this.get_selections().add(rowData);
            row.addClass(this.CSS_SELECTED);
            this._trigger("click");

            if (!isRowSelected || isMutliSelection) {
                this._trigger("change");
            }

        }
        else {

            if (!isRowSelected) {
                this.get_selections().add(rowData);
                row.addClass(this.CSS_SELECTED);
                this._trigger("click");
            }
            else {
                this.get_selections().remove(rowData);
                row.removeClass(this.CSS_SELECTED);
            }

            this._trigger("change");

        }

    },

    _row_onDblClick: function (e) {
        this._trigger("dblclick");
    },

    _row_onMouseDown: function (e) {

        var row = $(e.target).closest(this.QRY_ROW),
            isRightClick = e.button === 2,
            isRightClickEnabled = this.get_options().selection.onRightClick;

        if (isRightClick && isRightClickEnabled) {

            if (!row.hasClass(this.CSS_SELECTED)) {
                this.clear();
                row.addClass(this.CSS_SELECTED);
                this.get_selections().add();
            }

        }

        this._trigger("mousedown");

    },

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

    clear: function () {
        this._clear();
        this._trigger("change");
    },

    add: function (data) {
        this.get_selections().add(data);
        this._trigger("change");
    },

    remove: function (item) {
        this.get_selections().remove(item);
        this._trigger("change");
    },

    addMessage: function (message) {
        ProspectDirector.Web.UI.Utilities.Kendo.Grid.addMessage(this.get_gridDomNode(), message);
    },

    removeMessage: function () {
        ProspectDirector.Web.UI.Utilities.Kendo.Grid.removeMessage(this.get_gridDomNode());
    },

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

    _setDefaultMessage: function () {

        if (this.get_dataSource().data().length === 0) {
            this.addMessage("No Records");
        }
        else {
            this.removeMessage();
        }

    },

    _clear: function () {
        this.get_gridDomNode().find(this.QRY_SELECTED).removeClass(this.CSS_SELECTED);
        this.get_selections().clear();
    },

    _getRowData: function (domNode) {

        var uid = $(domNode).data("uid"),
            result = this.get_dataSource().getByUid(uid);

        if (result !== undefined && result !== null) {
            result = result.toJSON();
        }

        return result;
    },

    _trigger: function (eventName) {

        $(this).trigger(eventName, {
            selections: this.get_selections(),
            count: this.get_selections().count()
        });

    },

    _restore: function () {

        var that = this;

        this.get_selections().toKeysList().each(function (index, key) {

            var row = that.get_grid().dataSource.get(key);

            if (row) {

                dom = that.get_gridDomNode().find("tr[data-uid=" + row.uid + "]");

                if (dom.length === 1) {
                    dom.addClass(that.CSS_SELECTED);
                }

            }

        });

    },

    _readDataSource: function () {
        this.get_grid().dataSource._skip = 0;
        this.get_grid().read();
    }

});