/**
 * This is the class that takes care of pivot grid mouse events.
 *
 * @private
 */
Ext.define('Ext.pivot.feature.PivotEvents',{
    alternateClassName: [
        'Mz.pivot.feature.PivotEvents'
    ],
 
    extend: 'Ext.grid.feature.Feature',
    
    alias: 'feature.pivotevents',
 
    requires: [
        'Ext.pivot.feature.PivotStore'
    ],
 
    eventPrefix:    'pivotcell',
    eventSelector:  '.' + Ext.baseCSSPrefix + 'grid-cell',
 
    // this cls is used to catch events on the summary data rows (not on the header)
    summaryDataCls:             Ext.baseCSSPrefix + 'pivot-summary-data',
    summaryDataSelector:        '.' + Ext.baseCSSPrefix + 'pivot-summary-data',
    cellSelector:               '.' + Ext.baseCSSPrefix + 'grid-cell',
    groupHeaderCls:             Ext.baseCSSPrefix + 'pivot-grid-group-header',
    groupHeaderCollapsibleCls:  Ext.baseCSSPrefix + 'pivot-grid-group-header-collapsible',
 
    // summary rows styling
    summaryRowCls:              Ext.baseCSSPrefix + 'pivot-grid-group-total',
    summaryRowSelector:         '.' + Ext.baseCSSPrefix + 'pivot-grid-group-total',
    grandSummaryRowCls:         Ext.baseCSSPrefix + 'pivot-grid-grand-total',
    grandSummaryRowSelector:    '.' + Ext.baseCSSPrefix + 'pivot-grid-grand-total',
 
    init: function(grid){
        var me = this;
        
        me.initEventsListeners();
 
        // if summaryRowCls or grandSummaryRowCls are changed then the selectors should match the new classes otherwise
        // events handling will have problems
        me.summaryRowSelector = '.' + me.summaryRowCls;
        me.grandSummaryRowSelector = '.' + me.grandSummaryRowCls;
 
        me.callParent(arguments);
 
    },
    
    destroy: function(){
        var me = this;
        
        me.destroyEventsListeners();
        
        Ext.destroy(me.dataSource);
        me.view = me.grid = me.gridMaster = me.matrix = me.dataSource = null;
        
        me.callParent(arguments);
    },
 
    initEventsListeners: function(){
        var me = this;
        
        me.eventsViewListeners = me.view.on(Ext.apply({
            scope:          me,
            destroyable:    true
        }, me.getViewListeners() || {}));
 
        me.gridListeners = me.grid.on(Ext.apply({
            scope:          me,
            destroyable:    true
        }, me.getGridListeners() || {}));
    },
    
    getViewListeners: function(){
        var me = this,
            listeners = {
                afterrender:    me.onViewAfterRender
            };
        
        listeners[me.eventPrefix + 'click'] = me.onCellEvent;
        listeners[me.eventPrefix + 'dblclick'] = me.onCellEvent;
        listeners[me.eventPrefix + 'contextmenu'] = me.onCellEvent;
        
        return listeners;
    },
    
    getGridListeners: Ext.emptyFn,
 
    destroyEventsListeners: function(){
        Ext.destroyMembers(this, 'eventsViewListeners', 'gridListeners');
        this.eventsViewListeners = this.gridListeners = null;
    },
    
    onViewAfterRender: function(){
        var me = this,
            lockPartner;
        
        me.gridMaster = me.view.up('pivotgrid');
        me.matrix = me.gridMaster.getMatrix();
 
        // Share the GroupStore between both sides of a locked grid
        lockPartner = me.lockingPartner;
        if (lockPartner && lockPartner.dataSource) {
            me.dataSource = lockPartner.dataSource;
        } else {
            me.dataSource = new Ext.pivot.feature.PivotStore({
                store:          me.grid.store,
                matrix:         me.matrix,
                grid:           me.gridMaster,
                clsGrandTotal:  me.gridMaster.clsGrandTotal,
                clsGroupTotal:  me.gridMaster.clsGroupTotal,
                summaryDataCls: me.summaryDataCls,
                rowCls:         me.rowCls
            });
        }
    },
    
    getRowId: function(record){
        return this.view.id + '-record-' + record.internalId;
    },
 
    getRecord: function(row){
        return this.view.getRecord(row);
    },
    
    onCellEvent: function(view, tdCell, e){
        var me = this,
            row = Ext.fly(tdCell).findParent(me.summaryDataSelector) || Ext.fly(tdCell).findParent(me.summaryRowSelector),
            record = me.getRecord(row),
            params = {
                grid:       me.gridMaster,
                view:       me.view,
                cellEl:     tdCell
            },
            colIndex, ret, eventName, column, colDef, leftKey, topKey,
            matrix, leftItem, topItem;
        
        if(!row || !record){
            return false;
        }
 
        matrix = me.gridMaster.getMatrix();
        leftKey = me.dataSource.storeInfo[record.internalId].leftKey;
        leftItem = matrix.leftAxis.findTreeElement('key', leftKey);
        leftItem = leftItem ? leftItem.node : null;
        row = Ext.fly(row);
        
        if(row.hasCls(me.grandSummaryRowCls)){
            // we are on the grand total row
            eventName = 'pivottotal';
        }else if(row.hasCls(me.summaryRowCls)){
            // we are on a group total row
            eventName = 'pivotgroup';
        }else if(row.hasCls(me.summaryDataCls)){
            // we are on a pivot item row
            eventName = 'pivotitem';
        }
        
        colIndex = Ext.getDom(tdCell).getAttribute('data-columnid');
        column = me.getColumnHeaderById(colIndex);
        
        Ext.apply(params, {
            columnId:   colIndex,
            column:     column,
            leftKey:    leftKey,
            leftItem:   leftItem
        });
        
        if(Ext.fly(tdCell).hasCls(me.groupHeaderCls)){
            // it's a header cell
        }else if(column){
            eventName += 'cell';
            colDef = me.getTopAxisGroupByDataIndex(column.dataIndex);
            if(colDef){
                topKey = colDef.col;
                topItem = matrix.topAxis.findTreeElement('key', topKey);
 
                Ext.apply(params, {
                    topKey:         topKey,
                    topItem:        topItem ? topItem.node : null,
                    dimensionId:    colDef.agg
                });
            }
        }
        
        ret = me.gridMaster.fireEvent(eventName + e.type, params, e);
        
        if(ret !== false && e.type == 'click' && Ext.fly(tdCell).hasCls(me.groupHeaderCollapsibleCls)){
            if(leftItem.expanded){
                leftItem.collapse();
                me.view.focusNode(leftItem.records.collapsed);
            }else{
                leftItem.expand();
                me.view.focusNode(leftItem.records.expanded);
            }
        }
        
        return false;
    },
    
    getColumnHeaderById: function(columnId){
        var columns = this.view.getGridColumns(),
            i;
        
        for(= 0; i < columns.length; i++){
            if(columns[i].id === columnId){
                return columns[i];
            }
        }
    },
    
    getTopAxisGroupByDataIndex: function(dataIndex){
        var columns = this.gridMaster.matrix.getColumns(),
            i;
            
        for(= 0; i < columns.length; i++){
            if(columns[i].name === dataIndex){
                return columns[i];
            }
        }
    }
 
 
});