/**
 *
 * This plugin allows the user to view all records that were aggregated for a specified cell.
 *
 * The user has to double click that cell to open the records viewer.
 *
 * If a {@link Ext.pivot.matrix.Remote Remote} matrix is used then the plugin requires
 * an url to be provided to fetch the records for a left/top keys pair.
 *
 */
Ext.define('Ext.pivot.plugin.DrillDown', {
    alternateClassName: [
        'Mz.pivot.plugin.DrillDown'
    ],
 
    alias: [
        'plugin.pivotdrilldown',
        'plugin.mzdrilldown'
    ],
 
    extend: 'Ext.AbstractPlugin',
    
    requires: [
        'Ext.pivot.Grid',
        'Ext.window.Window',
        'Ext.data.proxy.Memory',
        'Ext.data.Store',
        'Ext.toolbar.Paging'
    ],
 
    mixins: {
        observable: 'Ext.util.Observable'
    },
    
    /**
     * @cfg {Ext.grid.column.Column[]} [columns] Specify which columns should be visible in the grid.
     *
     * Use the same definition as for a grid column. Header and dataIndex are the most important ones.
     */
    columns:     null,
    /**
     * @cfg {Number} width Width of the viewer's window.
     */
    width:        400,
    /**
     * @cfg {Number} height Height of the viewer's window.
     */
    height:        300,
    /**
     * @cfg {Ext.data.Store} remoteStore
     * Provide either a store config or a store instance when using a {@link Ext.pivot.matrix.Remote Remote} matrix on the pivot grid.
     *
     * The store will be remotely filtered to fetch records from the server.
     */
    remoteStore:    null,
    /**
     * @cfg {String} textWindow Viewer's window title.
     */
    textWindow: 'Drill down window',
    
    /**
     *  `"both"` (the default) - The plugin is added to both grids
     *  `"top"` - The plugin is added to the containing Panel
     *  `"locked"` - The plugin is added to the locked (left) grid
     *  `"normal"` - The plugin is added to the normal (right) grid
     *
     * @private
    */
    lockableScope:  'top',
    
    init: function(grid){
        var me = this;
 
        //<debug> 
        // this plugin is available only for the pivot grid 
        if (!grid.isPivotGrid) {
            Ext.raise('This plugin is only compatible with Ext.pivot.Grid');
        }
        //</debug> 
 
        me.pivot = grid;
        me.pivotListeners = me.pivot.on({
            pivotitemcelldblclick:      me.runPlugin,
            pivotgroupcelldblclick:     me.runPlugin,
            pivottotalcelldblclick:     me.runPlugin,
            scope:                      me,
            destroyable:                true
        });
        
        me.callParent(arguments);        
    },
    
    destroy: function(){
        var me = this;
        
        Ext.destroyMembers(me, 'view', 'pivotListeners');
 
        me.pivot = me.view = me.pivotListeners = me.store = null;
 
        me.callParent(arguments);
    },
 
    /**
     *
     * @param {Ext.pivot.result.Base} result
     * @private
     */
    showView: function(result){
        var me = this,
            matrix = me.pivot.getMatrix(),
            columns = me.columns || [],
            fields, store, filters;
 
        if(!result){
            return;
        }
 
        if (!me.view) {
            
            switch(matrix.type){
                case 'local':
                    fields = matrix.store.model.getFields();
                    store = Ext.create('Ext.data.Store', {
                        pageSize: 25,
                        remoteSort: true,
                        fields: Ext.clone(fields),
                        proxy: {
                            type: 'memory',
                            reader: {
                                type: 'array'
                            },
                            enablePaging: true
                        }
                    });
                    // if no columns are defined then use those defined in the pivot grid store 
                    if (columns.length === 0) {
                        Ext.Array.each(fields, function (value, index, all) {
                            columns.push({
                                header: Ext.String.capitalize(value.name),
                                dataIndex: value.name
                            });
                        });
                    }
                    break;
 
                case 'remote':
                    store = Ext.getStore(me.remoteStore);
 
                    if(store){
                        store.setRemoteFilter(true);
                    }
 
                    //<debug> 
                    if(columns.length === 0){
                        Ext.raise('No columns defined for the drill down grid!');
                    }
                    //</debug> 
 
                    break;
 
                default:
                    return;
            }
 
            // create the window that will show the records 
            me.view = Ext.create('Ext.window.Window', {
                title: me.textWindow,
                width: me.width,
                height: me.height,
                layout: 'fit',
                modal: true,
                closeAction: 'hide',
                items: [{
                    xtype: 'grid',
                    border: false,
                    viewConfig: {
                        loadMask: false
                    },
                    columns: columns,
                    store: store,
                    dockedItems: [{
                        itemId: 'idPager',
                        xtype: 'pagingtoolbar',
                        store: store,   // same store GridPanel is using 
                        dock: 'bottom',
                        displayInfo: true
                    }]
                }]
            });
 
            me.store = store;
        }
 
        switch(matrix.type){
            case 'local':
                me.store.getProxy().data = result.records;
                me.store.load();
                me.view.down('#idPager').moveFirst();
                break;
 
            case 'remote':
                filters = Ext.Array.merge(me.getFiltersFromParams(result.getLeftAxisItem() ? result.getLeftAxisItem().data : {}), me.getFiltersFromParams(result.getTopAxisItem() ? result.getTopAxisItem().data : {}));
                me.store.clearFilter(filters.length > 0);
                me.store.addFilter(filters);
                break;
 
            default:
                return;
        }
 
        me.view.show();
    },
 
    runPlugin: function(params, e, eOpts){
        // do nothing if the plugin is disabled 
        if(this.disabled) {
            return;
        }
 
        this.showView(this.pivot.getMatrix().results.get(params.leftKey, params.topKey));
    },
 
    getFiltersFromParams: function(obj){
        var filters = [],
            i, len, keys;
 
        if(Ext.isObject(obj)) {
            keys = Ext.Object.getKeys(obj);
            len = keys.length;
 
            for (= 0; i < len; i++) {
                filters.push({
                    property: keys[i],
                    exactMatch: true,
                    value: obj[keys[i]]
                });
            }
        }
 
        return filters;
    }
 
});