/**
 * 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.
 *
 * **Note:** If a {@link Ext.pivot.matrix.Remote Remote} matrix is used then the plugin requires
 * a {@link #remoteStore} 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.plugin.Abstract',
    
    requires: [
        'Ext.pivot.Grid',
        'Ext.window.Window',
        'Ext.data.proxy.Memory',
        'Ext.data.Store',
        'Ext.toolbar.Paging'
    ],
 
    /**
     * Fired on the pivot component when the drill down window is visible
     *
     * @event showdrilldownpanel
     * @param {Ext.window.Window} panel Drill down window
     */
 
    /**
     * Fired on the pivot component when the drill down window is hidden
     *
     * @event hidedrilldownpanel
     * @param {Ext.window.Window} panel 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',
 
    config: {
        /**
         * @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,
        /**
         * @private
         */
        grid: null,
        /**
         * @private
         */
        view: null
    },
 
    /**
     * @cfg {String} textWindow Viewer's window title.
     */
    textWindow: 'Drill down window',
 
    init: function(grid){
        //<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>
 
        this.setGrid(grid);
        return this.callParent([grid]);
    },
 
    destroy: function(){
        this.setConfig({
            grid: null,
            view: null
        });
        this.callParent();
    },
 
    updateGrid: function(grid){
        Ext.destroy(this.gridListeners);
 
        if(grid){
            this.gridListeners = grid.on({
                pivotitemcelldblclick:      'showPanel',
                pivotgroupcelldblclick:     'showPanel',
                pivottotalcelldblclick:     'showPanel',
                scope:                      this,
                destroyable:                true
            });
        }
    },
 
    updateView: function(view, oldView){
        Ext.destroy(oldView);
    },
 
    showPanel: function(params, e, eOpts){
        var me = this,
            grid = me.getGrid(),
            matrix = grid.getMatrix(),
            columns = Ext.Array.from(me.getColumns() || []),
            result, fields, store, filters, view,
            i, len, value;
 
        // do nothing if the plugin is disabled
        if(me.disabled) {
            return;
        }
 
        result = matrix.results.get(params.leftKey, params.topKey);
 
        if(!result){
            return;
        }
 
        switch(matrix.type){
            case 'local':
                fields = matrix.store.model.getFields();
                store = new 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) {
                    len = fields.length;
                    for(= 0; i < len; i++){
                        value = fields[i];
                        columns.push({
                            text: Ext.String.capitalize(value.name),
                            dataIndex: value.name
                        });
                    }
                }
                store.getProxy().data = result.records;
                store.load();
                break;
 
            case 'remote':
                store = Ext.getStore(me.getRemoteStore());
 
                if(store){
                    store.setRemoteFilter(true);
                }
 
                //<debug>
                if(columns.length === 0){
                    Ext.raise('No columns defined for the drill down grid!');
                }
                //</debug>
 
                filters = Ext.Array.merge(me.getFiltersFromParams(result.getLeftAxisItem() ? result.getLeftAxisItem().data : {}), me.getFiltersFromParams(result.getTopAxisItem() ? result.getTopAxisItem().data : {}));
                store.clearFilter(true);
                if(filters.length > 0) {
                    store.addFilter(filters);
                }else{
                    store.load();
                }
                break;
 
            default:
                return;
        }
 
        // create the window that will show the records
        view = me.createPanel(store, columns);
        view.show();
        me.setView(view);
        grid.fireEvent('showdrilldownpanel', view);
    },
 
    createPanel: function(store, columns){
        var me = this;
 
        return new Ext.window.Window({
            title: me.textWindow,
            width: me.getWidth(),
            height: me.getHeight(),
            layout: 'fit',
            modal: true,
            closeAction: 'hide',
            items: [{
                xtype: 'grid',
                border: false,
                viewConfig: {
                    loadMask: false
                },
                columns: columns,
                store: store,
                dockedItems: [{
                    xtype: 'pagingtoolbar',
                    store: store,   // same store GridPanel is using
                    dock: 'bottom',
                    displayInfo: true
                }]
            }],
            listeners: {
                close: 'onClosePanel',
                scope: me
            }
        });
    },
 
    onClosePanel: function(){
        var view = this.getView();
 
        this.getGrid().fireEvent('hidedrilldownpanel', view);
        this.setView(null);
    },
 
    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;
    }
 
});