/**
 * @class Ext.selection.CheckboxModel
 * @extends Ext.selection.RowModel
 *
 * A selection model that renders a column of checkboxes that can be toggled to
 * select or deselect rows. The default mode for this selection model is MULTI.
 *
 * The selection model will inject a header for the checkboxes in the first view
 * and according to the 'injectCheckbox' configuration.
 */

Ext.define('Ext.selection.CheckboxModel', {
    alias
: 'selection.checkboxmodel',
    extend
: 'Ext.selection.RowModel',

    /**
     * @cfg {String} mode
     * Modes of selection.
     * Valid values are SINGLE, SIMPLE, and MULTI. Defaults to 'MULTI'
     */

    mode
: 'MULTI',

    /**
     * @cfg {Mixed} injectCheckbox
     * Instructs the SelectionModel whether or not to inject the checkbox header
     * automatically or not. (Note: By not placing the checkbox in manually, the
     * grid view will need to be rendered 2x on initial render.)
     * Supported values are a Number index, false and the strings 'first' and 'last'.
     * Default is 0.
     */

    injectCheckbox
: 0,

    /**
     * @cfg {Boolean} checkOnly <tt>true</tt> if rows can only be selected by clicking on the
     * checkbox column (defaults to <tt>false</tt>).
     */

    checkOnly
: false,

   
// private
    checkerOnCls
: Ext.baseCSSPrefix + 'grid-hd-checker-on',

    bindComponent
: function() {
       
this.sortable = false;
       
this.callParent(arguments);

       
var view     = this.views[0],
            headerCt
= view.headerCt;

       
if (this.injectCheckbox !== false) {
           
if (this.injectCheckbox == 'first') {
               
this.injectCheckbox = 0;
           
} else if (this.injectCheckbox == 'last') {
               
this.injectCheckbox = headerCt.getColumnCount();
           
}
            headerCt
.add(this.injectCheckbox,  this.getHeaderConfig());
       
}
        headerCt
.on('headerclick', this.onHeaderClick, this);
   
},

    /**
     * Toggle the ui header between checked and unchecked state.
     * @param {Boolean} isChecked
     * @private
     */

    toggleUiHeader
: function(isChecked) {
       
var view     = this.views[0],
            headerCt
= view.headerCt,
            checkHd  
= headerCt.child('gridcolumn[isCheckerHd]');

       
if (checkHd) {
           
if (isChecked) {
                checkHd
.el.addCls(this.checkerOnCls);
           
} else {
                checkHd
.el.removeCls(this.checkerOnCls);
           
}
       
}
   
},

    /**
     * Toggle between selecting all and deselecting all when clicking on
     * a checkbox header.
     */

    onHeaderClick
: function(headerCt, header, e) {
       
if (header.isCheckerHd) {
            e
.stopEvent();
           
var isChecked = header.el.hasCls(Ext.baseCSSPrefix + 'grid-hd-checker-on');
           
if (isChecked) {
               
// We have to supress the event or it will scrollTo the change
               
this.deselectAll(true);
           
} else {
               
// We have to supress the event or it will scrollTo the change
               
this.selectAll(true);
           
}
       
}
   
},

    /**
     * Retrieve a configuration to be used in a HeaderContainer.
     * This should be used when injectCheckbox is set to false.
     */

    getHeaderConfig
: function() {
       
return {
            isCheckerHd
: true,
            text
: '&#160;',
            width
: 24,
            sortable
: false,
            fixed
: true,
            hideable
: false,
            menuDisabled
: true,
            dataIndex
: '',
            cls
: Ext.baseCSSPrefix + 'column-header-checkbox ',
            renderer
: Ext.Function.bind(this.renderer, this)
       
};
   
},

    /**
     * Generates the HTML to be rendered in the injected checkbox column for each row.
     * Creates the standard checkbox markup by default; can be overridden to provide custom rendering.
     * See {@link Ext.grid.column.Column#renderer} for description of allowed parameters.
     */

    renderer
: function(value, metaData, record, rowIndex, colIndex, store, view) {
        metaData
.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
       
return '<div class="' + Ext.baseCSSPrefix + 'grid-row-checker">&#160;</div>';
   
},

   
// override
    onRowMouseDown
: function(view, record, item, index, e) {
        view
.el.focus();
       
var me = this,
            checker
= e.getTarget('.' + Ext.baseCSSPrefix + 'grid-row-checker');

       
// checkOnly set, but we didn't click on a checker.
       
if (me.checkOnly && !checker) {
           
return;
       
}

       
if (checker) {
           
var mode = me.getSelectionMode();
           
// dont change the mode if its single otherwise
           
// we would get multiple selection
           
if (mode !== 'SINGLE') {
                me
.setSelectionMode('SIMPLE');
           
}
            me
.selectWithEvent(record, e);
            me
.setSelectionMode(mode);
       
} else {
            me
.selectWithEvent(record, e);
       
}
   
},

    /**
     * Synchronize header checker value as selection changes.
     * @private
     */

    onSelectChange
: function() {
       
this.callParent(arguments);

       
// check to see if all records are selected
       
var hdSelectStatus = this.selected.getCount() === this.store.getCount();
       
this.toggleUiHeader(hdSelectStatus);
   
}
});