/*
 *  Copyright 2016 Anyware Services
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
 * This tool is an abstract class allowing to search some items, given some configurable criteria, and display the results in a grid (with configurable columns).
 */
Ext.define('Ametys.plugins.cms.search.AbstractSearchTool', {
    extend: 'Ametys.tool.Tool',
    
    statics: {
        /**
         * @property {Number}
         * @readonly
         * @static
         * The number of records to display by 'page'
         */
        PAGE_SIZE: 50,
        
        /**
         * @property {Number}
         * @readonly
         * @static
         * The max height of search form
         */
        FORM_DEFAULT_MAX_HEIGHT: 400,
        
        /**
         * @property {Number}
         * @readonly
         * @static
         * The min height of search form
         */
        FORM_DEFAULT_MIN_HEIGHT: 100,
        
        /**
         * @property {Number}
         * @readonly
         * @static
         * The default ratio of form's height
         */
        FORM_DEFAULT_HEIGHT_RATIO: 1/3,
        
        /**
         * @property {Number}
         * @readonly
         * @static
         * The max ratio of form's height
         */
        FORM_DEFAULT_MAX_HEIGHT_RATIO: 2/3,
        
        /**
         * @property {Number}
         * @readonly
         * @static
         * The default width for label's fields 
         */
        FORM_DEFAULT_LABEL_WIDTH: 120,
        
        /**
         * @property {Number}
         * @readonly
         * @static
         * The default width for of form's fields
         */
        FORM_DEFAULT_FIELD_WIDTH: 300
    },
    
    /**
     * @cfg {Number} [formMaxHeight=Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_MAX_HEIGHT] The max height of the form panel
     */
    /**
     * @cfg {Number} [formMinHeight=Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_MIN_HEIGHT] The min height of the form panel
     */
    /**
     * @cfg {Number} [formHeightRatio=Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_HEIGHT_RATIO] The ratio of form's height
     */
    /**
     * @cfg {Number} [formMaxHeightRatio=Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_MAX_HEIGHT_RATIO] The max ratio of form's height
     */
    /**
     * @cfg {Number} [formLabelWidth=Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_LABEL_WIDTH] The width for label's fields
     */
    /**
     * @cfg {Number} [formFieldWidth=Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_FIELD_WIDTH] The width for of form's fields
     */
    /**
     * @cfg {Boolean} [enablePagination=true] Enable the pagination for the grid.
     */
    /**
     * @property {Ext.panel.Panel} mainPanel The main panel of the tool
     * @protected
     */
    /**
     * @property {Ext.panel.Panel} searchPanel The panel in the top of the tool, which displays the search criteria
     * @protected
     */
    /**
     * @property {Ametys.form.ConfigurableFormPanel} form The simple search form
     * @protected
     */
    /**
     * @property {Ext.data.Store} store The store with the searched items
     * @protected
     */
    /**
     * @property {String} _modelName The unique name of model used by the store
     * @private
     */
    /**
     * @property {Ext.grid.Panel} grid The grid panel displaying the items (results)
     * @protected
     */
    
    /**
     * @property {Boolean} [_expanded=false] Set to true to always keep form expanded (default to false)
     * @private
     */
    
    /**
     * @private
     * @property {Boolean} _paramsHasChanged If set params was called but not applied. Will be applied on next focus.
     */
    
    /**
     * @property {Boolean} [_startSearchAtOpening=false] Set to true to start the search at the opening of the tool (default to false)
     * @private
     */
    
    /**
     * @property {Boolean} _updatingModel True if the search form, model and columns are currently being updated. If true, all launch searches will be cancelled.
     * @protected
     */
    
    /**
     * @cfg searchButtonText=plugin.cms:UITOOL_SEARCH_BUTTON_SEARCH The text for search button,
     */
    searchButtonText: "{{i18n plugin.cms:UITOOL_SEARCH_BUTTON_SEARCH}}",
    
    /**
     * @cfg searchButtonTooltipText=plugin.cms:UITOOL_SEARCH_BUTTON_SEARCH_DESC The tooltip text for search button,
     */
    searchButtonTooltipText: "{{i18n plugin.cms:UITOOL_SEARCH_BUTTON_SEARCH_DESC}}",
    
    /**
     * @cfg searchButtonIconCls=ametysicon-magnifier12 The CSS class for search button's icon,
     */
    searchButtonIconCls: 'ametysicon-magnifier12',
    
    /**
     * @cfg cancelButtonText=plugin.cms:UITOOL_SEARCH_BUTTON_CANCEL The text for cancel button,
     */
    cancelButtonText: "{{i18n plugin.cms:UITOOL_SEARCH_BUTTON_CANCEL}}",
    
    /**
     * @cfg cancelButtonTooltipText=plugin.cms:UITOOL_SEARCH_BUTTON_CANCEL_DESC The tooltip text for cancel button,
     */
    cancelButtonTooltipText: "{{i18n plugin.cms:UITOOL_SEARCH_BUTTON_CANCEL_DESC}}",
    
    /**
     * @cfg cancelButtonIconCls=ametysicon-forbidden1 The CSS class for cancel search button's icon,
     */
    cancelButtonIconCls: 'ametysicon-forbidden1',
        
    constructor: function(config)
    {
        this.callParent(arguments);
        
        if (!this.formMaxHeight)
        {
            this.formMaxHeight = Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_MAX_HEIGHT;
        }
        
        if (!this.formMinHeight)
        {
            this.formMinHeight = Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_MIN_HEIGHT;
        }
        
        if (!this.formHeightRatio)
        {
            this.formHeightRatio = Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_HEIGHT_RATIO;
        }
        
        if (!this.formMaxHeightRatio)
        {
            this.formMaxHeightRatio = Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_MAX_HEIGHT_RATIO;
        }
        
        if (!this.formLabelWidth)
        {
            this.formLabelWidth = Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_LABEL_WIDTH;
        }
        
        if (!this.formFieldWidth)
        {
            this.formFieldWidth = Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_FIELD_WIDTH;
        }
        
        this.enablePagination = config.enablePagination !== false;
    },
    
    /**
     * The state id
     * Should be overriden for tools using the basic tool factory.
     * @return {String} The state id
     */
    getStateId: function()
    {
        return this.getId();
    },
    
    createPanel: function()
    {
        this._updatingModel = true;
        
        this.searchPanel = this._createSearchFormPanel();
        
        var me = this;
        this.mainPanel = Ext.create('Ext.panel.Panel', {
            cls: 'search-tool',
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            border: false,
            items: [ 
                    this.searchPanel, 
                    {
                        split: true,
                        xtype: 'panel',
                        flex: 1,
                        border: false,
                        layout: 'border',
                        
                        stateful: true,
                        stateId: this.getStateId() + '$result-panel',
            
                        items: this.getBottomPanelItems(),
                        listeners: {
                            'resize': function(cmp, width, height)
                            {
                                if (!this.collapsed)
                                {
                                    this._lastKnownFlex = this.flex
                                }
                            }
                        },            
                        
                        applyState: function (state)
                        {
                            this.flex = state.flex;
                        },
                        
                        getState: function ()
                        {
                            // Save the height ratio
                            return {
                                flex: this.collapsed ? this._lastKnownFlex : this.flex
                            }
                        }
                    }
            ]
        });
        
        return this.mainPanel;
    },
    
    /**
     * Creates the panel of search criteria
     * @protected
     */
    _createSearchFormPanel: function()
    {
        let me = this;
        
        var cfg = this._getSearchFormPanelConfig(),
            items = this.getSearchFormPanelSubItems(),
            layout = items.length == 1 ? 'fit' : 'card';
        var panelCfg = Ext.apply(cfg, {
            split: false,
            
            border: false,
            cls: 'criteria',
            
            ui: 'light',
            header: {
                titlePosition: 1
            },
            
            stateful: true,
            stateId: this.getStateId() + '$search-form',
            
            title: "{{i18n plugin.cms:UITOOL_SEARCH_CRITERIA}}",
            collapsible: true,
            titleCollapse: true,
            animCollapse: false,
            scrollable: 'vertical',
            
            referenceHolder: true,
            defaultButton: 'launch',
            defaultButtonTarget: 'el',
            
            minHeight: Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_MIN_HEIGHT,
            maxHeight: Ametys.plugins.cms.search.AbstractSearchTool.FORM_DEFAULT_MAX_HEIGHT,
            flex: 0.3,
            
            layout: layout,
            
            items: items,
            
            listeners: {
                'resize': function(cmp, width, height)
                {
                    if (!this.collapsed)
                    {
                        this._lastKnownFlex = this.flex
                    }
                }
            },            
            
            applyState: function (state)
            {
                this.flex = state.flex;
            },
            
            getState: function ()
            {
                // Save the height ratio
                return {
                    flex: this.collapsed ? this._lastKnownFlex : this.flex
                }
            }
        });
        
        return Ext.create('Ext.Panel', panelCfg);
    },
    
    /**
     * @template
     * @protected
     * Get the configuration object of the search panel
     * @return {Object} The configuration object
     */
    _getSearchFormPanelConfig: function()
    {
        return {
            bbar: this._getSearchFormPanelBBar()
        };
    },
    
    /**
     * @template
     * @protected
     * Get the items of the optional bottom bar of the criteria panel
     * @return {Array} The bottom bar configuration array
     */
    _getSearchFormPanelBBar: function()
    {
        var items = this._getDefaultButtons();
        return items;
    },
    
    /**
     * @private
     * Get the default buttons
     * @return {Array} The default buttons
     */
    _getDefaultButtons: function() 
    {
        var items = [{
            // Search
            itemId: 'search',
            reference: 'launch',
            text: this.searchButtonText,
            iconCls: this.searchButtonIconCls, 
            handler: this._launchSearch,
            scope: this,
            tooltip: {
                title: this.searchButtonText,
                text: this.searchButtonTooltipText,
                glyphIcon: this.searchButtonIconCls,
                inribbon: false
            }
        }, 
        {
            // Cancel
            itemId: 'cancel',
            iconCls: this.cancelButtonIconCls,
            handler: this._stopSearch,
            scope: this,
            disabled: true,
            tooltip: {
                title: this.cancelButtonText,
                text: this.cancelButtonTooltipText,
                glyphIcon: this.cancelButtonIconCls,
                inribbon: false
            }
        }];
        
        return items;
    },
    
        
    /**
     * @template
     * @protected
     * Gets the sub-items of the search form panel. By default, only the simple search form panel.
     * @return {Ext.Component[]} The sub-items of the search form panel to display (in a card layout)
     */
    getSearchFormPanelSubItems: function()
    {
        this.form = this._createSimpleSearchFormPanel();
        return [this.form];
    },
    
        
    /**
     * Creates the simple form panel
     * @private
     */
    _createSimpleSearchFormPanel: function()
    {
        var formCfg = {
            itemId: 'simple-search-form-panel',
            cls: 'simple-search-form-panel',
            scrollable:  'vertical',
            
            fieldsetLayout: {
                 type: 'enhancedcolumns',
                 minColWidth: this.formFieldWidth,
                 ignoreItem: function (item) { return item.getInitialConfig('widget') == 'edition.hidden'; }
            },
            
            labelAlign: 'top',
            
            additionalWidgetsConf: {
                searchTool: true
            },
            additionalWidgetsConfFromParams: {
                contentType: 'contentType' // some widgets requires the contentType configuration  
            },
            
            withTitleOnLabels: true,
        };
        
        return Ext.create('Ametys.form.ConfigurableFormPanel', formCfg);
    },
    
    /**
     * @template
     * @protected
     * Gets the items of the bottom panel. By default, only the result grid.
     * @return {Ext.Component[]} The items to display in the bottom panel
     */
    getBottomPanelItems: function()
    {
        this.store = this.createStore();
        
        // Create interceptor to prevent loading while model, columns and form are not updated
        this.store.load = Ext.Function.createInterceptor(this.store.load, function() { return !this._updatingModel; }, this);
        this.grid = this._createResultGrid(this.store);
        
        // The Stateful should wait for a reconfigure before operating
        this.grid.applyState = Ext.Function.createInterceptor(this.grid.applyState, function() { return this._reconfigured === true; }, this);
        this.grid.initState = Ext.Function.createInterceptor(this.grid.initState, function() { return this._reconfigured === true; }, this);
        this.grid.getState = Ext.Function.createInterceptor(this.grid.getState, function() { return this._reconfigured === true; }, this);
        this.grid.saveState = Ext.Function.createInterceptor(this.grid.saveState, function() { return this._reconfigured === true; }, this);
        this.grid.on('reconfigure', Ext.bind(this._onFirstGridReconfigure, this));
        
        return [this.grid];
    },
    
    /**
     * @private
     * Event the first time the grid is reconfigured
     */
    _onFirstGridReconfigure: function()
    {
        this._reconfigured = true;
    },
    
    /**
     * @protected
     * Get the store the grid should use as its data source.
     * @return {Ext.data.Store} The store
     */
    createStore: function()
    {
        this._createModel();
        var storeCfg = Ext.applyIf({
            model: this._modelName,
            autoDestroy: true,
            pageSize: Ametys.plugins.cms.search.AbstractSearchTool.PAGE_SIZE // seems useless due to this.store.setPageSize done later
        }, this._getStoreCfg());
        
        return Ext.create('Ext.data.Store', storeCfg);
    },
    
    /**
     * @template
     * @protected
     * Creates the model for the store.
     * Override this method for defining your own default fields
     * @param {Object[]} [fields] The fields for this model
     */
    _createModel: function(fields)
    {
        fields = fields || [
                    {name: 'id', mapping: 'id'}
        ];
                
        this._modelName = this.getId() + "-Ametys.plugins.cms.search.AbstractSearchTool.ContentEntry";
        
        if (Ext.data.schema.Schema.get('default').hasEntity(this._modelName)) 
        {
            Ext.data.schema.Schema.get('default').getEntity(this._modelName).replaceFields(fields, true);
        }
        else
        {
            Ext.define(this._modelName, {
                extend: 'Ext.data.Model',
                schema: 'default',
                fields: fields
            });
        }
    },
    
    /**
     * @template
     * @protected
     * Get the config to be used to create the store.
     * @return {Object} The config object
     */
    _getStoreCfg: function()
    {
        throw new Error("This method is not implemented in " + this.self.getName());
    },
    
    /**
     * @template
     * @protected
     * Get the config to be used to create the reader for the store.
     * @return {Object} The config object
     */
    _getReaderCfg: function()
    {
        throw new Error("This method is not implemented in " + this.self.getName());
    },
    
    /**
     * @template
     * @protected
     * Create the grid panel for results.
     * The default implementation creates a Ext.grid.Panel no columns, grouping enabled and pagination toolbar is #cfg-enablePagination is true.
     * @param {Ext.data.Store} store The store to use for the grid. You MUST set this parameter as the 'store' configuration of the returned grid.
     * @return {Ext.grid.Panel} The created grid
     */
    _createResultGrid: function(store)
    {
        return Ext.create('Ext.grid.Panel', this._getResultGridCfg(store));
    },
    
    /**
     * @template
     * @protected
     * Get the configuration object for result grid.
     * The default implementation build a simple configuration with no columns, grouping enabled and pagination toolbar is #cfg-enablePagination is true.
     * @param {Ext.data.Store} store The store to use for the grid. You MUST set this parameter as the 'store' configuration of the returned grid.
     * @return {Ext.grid.Panel} The created grid
     */
    _getResultGridCfg: function(store)
    {
        var dockedItems = [];
        if (this.enablePagination)
        {
            dockedItems.push(this._getPaginationToolbarCfg(store));
        }
        
        return { 
            store: store,
            
            region: 'center',
            split: true,
            border: false,
            
            stateful: true,
            stateId: this.getStateId() + "$grid",
            
            columns: [], // columns will be set later
            
            features: [{
                ftype: 'grouping',
                groupHeaderTpl: [
                    '{columnName}: {name:this.formatName}',
                    {
                        formatName: function(name) {
                            return Ext.String.trim(name.toString());
                        }
                    }
                ]
            }],
            
            viewConfig: {
                loadingText: "{{i18n plugin.cms:UITOOL_SEARCH_WAITING_MESSAGE}}"
            },
            
            dockedItems: dockedItems,
            
            listeners: {
                'selectionchange': Ext.bind(this._onSelectionChanged, this)
            }
        };
    },
    
    /**
     * @protected
     * Get the configuration for pagination toolbar
     * @param {Ext.data.Store} store The store of the grid
     * @return {Object} the object configuration for pagination toolbar
     */
    _getPaginationToolbarCfg: function(store)
    {
        return {
            xtype: 'pagingtoolbar',
            store: store,
            dock: 'bottom',
            displayInfo: true,
            displayMsg: "{{i18n plugin.cms:UITOOL_SEARCH_PAGEBAR_RESULT_1}}{0}{{i18n plugin.cms:UITOOL_SEARCH_PAGEBAR_RESULT_2}}{1}{{i18n plugin.cms:UITOOL_SEARCH_PAGEBAR_RESULT_3}}{2}",
            emptyMsg: "{{i18n plugin.cms:UITOOL_SEARCH_PAGEBAR_NO_RESULT}}"
        };
    },
    
    /**
     * Get the paging bar
     * @return {Ext.toolbar.Paging} The paging toolbar
     */
    getPaginationToolbar: function()
    {
        return this.enablePagination ? this.grid.getDockedItems('pagingtoolbar')[0] : null;
    },
    
    /**
     * @template
     * @protected
     * Listener when the selection has changed in result grid.
     * @param {Ext.selection.Model} sm the selection model
     * @param { Ext.data.Model[]} selected the selected record
     */
    _onSelectionChanged: function(sm, selected)
    {
        // nothing by default
    },
    
    /**
     * Launch the search
     * @param {Function} [callback] A callback function to execute after loading
     * @param {Object} [scope] The scope for callback function
     * @protected
     */
    _launchSearch: function(callback, scope)
    {
        this.showUpToDate();
        this._setGridDisabled(true);
        
        var opts = {};
        if (Ext.isFunction(callback))
        {
            opts = {
                callback: callback,
                scope: scope || this
            }
        }
        
        // FIXME
//      if (this.grid.enablePagination)
//      {
            this.store.loadPage(1, opts);
//      }
//      else
//      {
//          this.store.load();
//      }
    },
        
    /**
     * Stop the search in progress
     * @protected
     */
    _stopSearch: function()
    {
        var cancelCode = this.store.getProxy().getCancelCode();
        if (cancelCode)
        {
            Ametys.data.ServerComm.cancel(cancelCode);
        }
        
        if (this.grid.getView().loadMask)
        {
            this.grid.getView().loadMask.hide();
        }
        this._setGridDisabled(false);
    },
    
    /**
     * Enable or disable the grid columns and paging toolbar
     * @param {Boolean} disabled true to disable.
     * @protected
     */
    _setGridDisabled: function(disabled)
    {
        this._getSearchToolbar().items.get('search').setDisabled(disabled);
        this._getSearchToolbar().items.get('cancel').setDisabled(!disabled);
        
        if (this.enablePagination)
        {
            this.getPaginationToolbar().setDisabled(disabled);
        }
        
        var columns = this.grid.columnManager.getColumns();
        Ext.Array.each (columns, function(column) {
            column.setDisabled(disabled);
        })
    },
    
    /**
     * Return the docked form
     * @protected
     */
    _getFormPanel: function() 
    {
        return this.searchPanel;
    },
    
    /**
     * Return the search toolbar.
     * @protected
     */
    _getSearchToolbar: function() 
    {
        return this.searchPanel.getDockedItems('toolbar')[0];
    },
    
    setParams: function(params)
    {
        this.callParent(arguments);
        
        this._paramsHasChanged = true;
        
        this._expanded = params.expanded || false;
        this._startSearchAtOpening = params.startSearchAtOpening || false;
        
        this._possiblyCallInternalSetParams();
    },
    
    /**
     * @template
     * @protected
     * You can override this method in order to check if you want to call {@link #_internalSetParams}
     */
    _possiblyCallInternalSetParams: function()
    {
        this._internalSetParams(false);
    },

    /**
     * @protected
     * This method effectively change params IF params was changed since last call.
     * @param {Boolean} force True to force the re-setting of the params (for updating the model and columns for instance)
     */
    _internalSetParams: function(force)
    {
        if (!this._paramsHasChanged && !force)
        {
            return;
        }
        
        this._paramsHasChanged = false;
        
        this._retrieveCriteriaAndColumns(force);
    },
    
    /**
     * @template
     * @protected
     * Implement this method with your own logic for retrieving information about search criteria and columns.
     * It should call {@link #_configureSearchTool}, either directly, or as a callback function after a server call, so as to finish the process of drawing and configure the search tool.
     * @param {Boolean} force True to force the update of the model and columns even if not needed
     */
    _retrieveCriteriaAndColumns: function(force)
    {
        throw new Error("This method is not implemented in " + this.self.getName());
    },
    
    /**
     * @protected
     * Call this method to configure the search tool
     * @param {Object} criteria The search criteria
     * @param {Object} data The data object where to retrieve information in order to configure the columns
     * @param {Object[]} data.columns The columns definition
     * @param {Object} toolParams The parameters of the tool
     */
    _configureSearchTool: function(criteria, data, toolParams)
    {
        this._configureSearchForm(criteria);
        this._configureSearchColumns(data, toolParams);
        
        this._updatingModel = false;
        
        if (this._startSearchAtOpening)
        {
            this.refresh();
        }
    },
    
    /**
     * @protected
     * Configures the search criteria
     * @param {Object} criteria The search criteria
     */
    _configureSearchForm: function(criteria)
    {
        if (this.form instanceof Ametys.form.ConfigurableFormPanel)
        {
            this.form.configure(criteria);
        }
        
        if (this.form.items.get(0))
        {
            this.form.items.get(0).on('resize', this._initSearchFormHeight, this, {single: true});
        }
    },
    
    /**
     * @protected
     * Configures the search columns
     * @param {Object} data The data object where to retrieve information in order to configure the columns
     * @param {Object[]} data.columns The columns definition
     * @param {String} data.searchUrlPlugin The name of the plugin which will be set in the proxy of the store
     * @param {String} data.searchUrl The URL which will be set in the proxy of the store
     * @param {Number} [data.pageSize] The page size
     * @param {Object} toolParams The parameters of the tool
     */
    _configureSearchColumns: function(data, toolParams)
    {
        var fields = Ametys.plugins.cms.search.SearchGridHelper.getFieldsFromJson(data.columns);
        this._addDefaultContentFields(fields);
        var columns = this._getColumns(data);
        var sorters = toolParams.sort || Ametys.plugins.cms.search.SearchGridHelper.getSortersFromJson(columns, this.grid);
        
        this._configureProxy(data);
        
        if (data.pageSize != null && data.pageSize > 0)
        {
            this.store.setPageSize(data.pageSize);
        }
        
        // Update model
        this._createModel(fields);
        this.grid.reconfigure(this.store, columns);
        this.store.sorters = null; // There is no other way to clean old sorters...
        this.store.setSorters(sorters);
        
        // TODO Init search form from the default values.
        this._initSearchForm(toolParams);
    },
    
    /**
     * @protected
     * Call this method to get the columns
     * @param {Object[]} data.columns The columns definition
     */
    _getColumns: function(data)
    {
        return Ametys.plugins.cms.search.SearchGridHelper.getColumnsFromJson(data.columns, true, this.grid, false);
    },
        
    /**
     * @protected
     * Configures the search store proxy
     * @param {Object} data The data object where to retrieve information in order to configure the columns
     * @param {String} [data.searchUrlPlugin] The name of the plugin which will be set in the proxy of the store
     * @param {String} [data.searchUrl] The URL which will be set in the proxy of the store
     * @param {String} [data.searchRole] The role which will be set in the proxy of the store
     * @param {String} [data.searchMethodName] The method name which will be set in the proxy of the store
     */
    _configureProxy: function(data)
    {
        this.store.setProxy({
            type: 'ametys',
            plugin: data.searchUrlPlugin,
            url: data.searchUrl,
            role: data.searchRole,
            methodName: data.searchMethodName,
            cancelOutdatedRequest: true,
            reader: this._getReaderCfg()
        });
    },
    
    /**
     * @protected
     * Add some default field mappings to a field array
     * @param {Array} fields the field array to fill.
     */
    _addDefaultContentFields: function(fields)
    {
        if (fields != null && Ext.isArray(fields))
        {
            Array.prototype.push.apply(fields, this._getDefaultContentFields());
        }
    },
    
    /**
     * @protected
     * Gets the default field mappings
     * @return {Object[]} the default field mappings
     */
    _getDefaultContentFields: function()
    {
        return [{name: 'id'}];
    },
    
    refresh: function()
    {
        this.callParent(arguments);
        this._launchSearch();
    },
    
    /**
     * @protected
     * Fills the search form with initial search parameters
     * @param {Object} params The parameters of the tool
     * @param {Object} params.values The initial search parameters for the form 
     */
    _initSearchForm: function(params)
    {
        var form = this.form.getForm();
        Ext.Object.each(params.values, function(name, value) {
            var fd = form.findField(name);
            if (fd != null)
            {
                fd.setValue(value);
            }
        });
        
        this._onFormInitialized();
    },
    
    /**
     * @protected
     * Called when the form is initialized
     */
    _onFormInitialized: function()
    {
        if (this.form instanceof Ametys.form.ConfigurableFormPanel)
        {
            // Dummy "set values" call to send the formready event.
            this.form.setValues();
        }
    },
        
    /**
     * Initialize the height of the search form panel
     * @protected
     */
    _initSearchFormHeight: function()
    {
        var form = this._getFormPanel();
        var height = form.getSize().height;
        
        var maxHeight = Math.min(this.formMaxHeight, parseInt(this.mainPanel.getHeight() * this.formMaxHeightRatio));
        if (height > maxHeight)
        {
            height = maxHeight;
            form.setHeight(height);
        }
    },

    /**
     * Set the #cfg-title with a concatenation of original title and an additional one
     * @param {String} additionalTitle The prefix to add to the original title
     */
    setAdditionalTitle: function(additionalTitle)
    {
        var toolParams = this.getParams();
        toolParams.title = this.getInitialConfig('title') + (additionalTitle ? ' - ' + additionalTitle : '');
        Ametys.tool.Tool.prototype.setParams.apply(this, [toolParams]); // avoid tool refreshing
        
        this.setTitle(toolParams.title);
    },
});