Ext.ux.SingleRowSelectionModel = function(config){
    Ext.apply(this, config);
	
	this.selections = new Ext.util.MixedCollection(false, function(B) {
      return B.id}
    ); 

    this.selectedRow = null;
    this.selectedIndex = -1;

    this.addEvents(

        // params: selectionModel, index, record
        "beforerowselect",
        // params: selectionModel, index, record
        "beforerowdeselect",

        // params: selectionModel, index, record
        "rowselect",
        // params: selectionModel, index, record
        "rowdeselect",

        //params: selectionModel, newIndex, newRecord, oldIndex, oldRecord
        "selectionchange"
    );

    Ext.ux.SingleRowSelectionModel.superclass.constructor.call(this);
};

Ext.extend(Ext.ux.SingleRowSelectionModel, Ext.grid.AbstractSelectionModel,  {

    selectedRow: null,
    selectedIndex: -1,

    initEvents : function(){

        if (this.grid.enableDragDrop || this.grid.enableDrag){
            this.grid.enableDragDrop = false;
        }
        this.grid.on("rowmousedown", this.handleMouseDown, this);

        this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
            "up" : function(e){
                if (this.selectedIndex > 0)
                    this.selectPrevious();
            },
            "down" : function(e){
                if (this.selectedIndex < this.grid.store.getCount() - 1)
                    this.selectNext();
            },
            scope: this
        });

        var view = this.grid.view;
        view.on("refresh", this.onViewRefresh, this);
        view.on("rowupdated", this.onViewRowUpdated, this);
        view.on("rowremoved", this.onViewRowRemove, this);
    },
    
    getCount: function(){
        return this.selectedRow === null ? 0 : 1;
    },

    onViewRefresh : function(view){
        var ds = this.grid.store;
        var row = this.selectedRow;
        var index = this.selectedIndex;
        if (this.selectedIndex != -1 && this.selectedRow !== null){
            this.deselectRow(index);
        }
    },

    onViewRowRemove : function(view, index, record){
        if (this.selectedIndex == index){
            this.deselectRow(index);
        }
    },

    onViewRowUpdated : function(view, index, record){
        if(this.selectedIndex == index){
            view.onRowSelect(index);
        }
    },

    selectRow : function(index, preventViewNotify){
        if(this.locked || (index < 0 || index >= this.grid.store.getCount())) return;
        var record = this.grid.store.getAt(index);
        // select row and fire appropriate events
        if (this.selectedRow !== record){
            if (record && this.fireEvent("beforerowselect", this, index, record) !== false)
            {
                if(!preventViewNotify){
                    if (this.selectedRow !== null){
                        this.grid.getView().onRowDeselect(this.selectedIndex);
                    }
                    this.grid.getView().onRowSelect(index);
                }
                // is it a selection change or an actual selection
                if (this.selectedIndex != -1 && this.selectedRow !== null)
                    this.fireEvent("selectionchange", this, index, record, this.selectedIndex, this.selectedRow);
                else
                    this.fireEvent("rowselect", this, index, record);
                // store selection
                this.selectedRow = record;
                this.selectedIndex = index;
            }
        }
        else{
            if (record && this.fireEvent("beforerowselect", this, index, record) !== false){
                this.fireEvent("rowselect", this, index, record);
            }
        }
    },

    deselectRow : function(index, preventViewNotify){
        if(this.locked) return;
        var record = this.grid.store.getAt(index);
        if (record && this.fireEvent("beforerowdeselect", this, index, record) !== false){
            if(!preventViewNotify){
                this.grid.getView().onRowDeselect(index);
            }
            this.fireEvent("rowdeselect", this, index, record);
            // forget selection
            this.selectedRow = null;
            this.selectedIndex = -1;
        }
    },

    clearSelection : function(fast){
        if (this.locked) return;
        if (fast !== true){
            if (this.selectedRow !== null && this.selectedIndex != -1)
                this.deselectRow(this.selectedIndex);
        }
        else {
            this.selectedRow = null;
            this.selectedIndex = -1;
        }
    },

    handleMouseDown : function(g, index, e){
        if(e.button !== 0 || this.locked) return;
        if(e.ctrlKey && this.selectedIndex == index){
            this.deselectRow(index);
        }
        else {
            this.selectRow(index);
            this.grid.getView().focusRow(index);
        }
    },

    selectFirstRow : function(){
        this.selectRow(0);
    },

    selectLastRow : function(){
        var lastIndex = this.grid.store.getCount() - 1;
        this.selectRow(lastIndex);
    },

    selectNext : function(){
        if(this.hasNext()){
            this.selectRow(this.selectedIndex + 1);
            this.grid.getView().focusRow(this.selectedIndex);
        }
    },

    selectPrevious : function(){
        if(this.hasPrevious()){
            this.selectRow(this.selectedIndex - 1);
            this.grid.getView().focusRow(this.selectedIndex);
        }
    },

    hasNext : function(){
        return this.selectedIndex !== -1 && (this.selectedIndex + 1) < this.grid.store.getCount();
    },

    hasPrevious : function(){
        return this.selectedIndex > 0;
    },

    getSelected : function(){
        return this.selectedRow;
    },

    hasSelection : function(){
        return this.selectedRow !== null;
    },

    isSelected : function(index){
        return (this.selectedIndex == index);
    },

    isIdSelected : function(id){
        return (this.selectedRow !== null && this.selectedRow.id == id);
    },

    acceptsNav : function(row, col, cm){
        return !cm.isHidden(col) && cm.isCellEditable(col, row);
    },
	
    onEditorKey : function(field, e){
        var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
        if(k == e.TAB){
            e.stopEvent();
            ed.completeEdit();
            if(e.shiftKey){
                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
            }else{
                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
            }
        }else if(k == e.ENTER){
            e.stopEvent();
            ed.completeEdit();
            if(e.shiftKey){
                newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
            }else{
                newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
            }
        }else if(k == e.ESC){
            ed.cancelEdit();
        }
        if(newCell){
            g.startEditing(newCell[0], newCell[1]);
        }
    }
});