/*
 *  Copyright 2015 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.
 */

/**
 * The ODF catalog DAO.
 */
 Ext.define('Ametys.odf.catalog.CatalogDAO', {
 	singleton: true,
 	
 	constructor: function(config)
 	{
		/**
		 * @callable
		 * @member Ametys.odf.catalog.CatalogDAO
		 * @method createCatalog 
		 * Creates a new ODF catalog.
		 * This calls the method 'createCatalog' of the server DAO 'CatalogDAO'.
		 * @param {Object[]} parameters The parameters to transmit to the server method
		 * @param {String} parameters.title The title of the catalog
         * @param {String} parameters.name The code of the catalog
 		 * @param {String} parameters.catalogToCopy The catalog name to copy or null
		 * @param {Function} callback The function to call when the java process is over. Use options.scope for the scope. 
		 * @param {Object} callback.returnedValue The value return from the server. Null on error (please note that when an error occured, the callback may not be called depending on the value of errorMessage).
		 * @param {Object} callback.arguments Other arguments specified in option.arguments                 
		 * @param {Object} [options] Advanced options for the call.
		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerComm#callMethod errorMessage.
		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerComm#callMethod waitMessage.
		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods Ametys.data.ServerCaller#beforeServerCall and Ametys.data.ServerCaller#afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerComm#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerComm#callMethod cancelCode.
		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback beeing called with a null parameter. See Ametys.data.ServerComm#callMethod ignoreOnError.
		 */
		this.addCallables(
			{
			    role: "org.ametys.odf.catalog.CatalogDAO",
				methodName: "createCatalog",
	     		callback: {
	         		handler: this._createCatalogCb
	     		},
                priority: Ametys.data.ServerComm.PRIORITY_LONG_REQUEST,
                waitMessage: false,
				errorMessage: {
				    msg: "{{i18n PLUGINS_ODF_CATALOG_ADDCATALOGACTION_CREATIONFAILED}}",
				    category: Ext.getClassName(this)
				}
			}
		);
		
		/**
		 * @callable
		 * @member Ametys.odf.catalog.CatalogDAO
		 * @method editCatalog 
		 * Edits an ODF catalog.
		 * This calls the method 'editCatalog' of the server DAO 'CatalogDAO'.
		 * @param {Object[]} parameters The parameters to transmit to the server method
		 * @param {String} parameters.id The id of the catalog to edit
 		 * @param {String} parameters.title The title of the catalog
		 * @param {Function} callback The function to call when the java process is over. Use options.scope for the scope. 
		 * @param {Object} callback.returnedValue The value return from the server. Null on error (please note that when an error occured, the callback may not be called depending on the value of errorMessage).
		 * @param {Object} callback.arguments Other arguments specified in option.arguments                 
		 * @param {Object} [options] Advanced options for the call.
		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerComm#callMethod errorMessage.
		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerComm#callMethod waitMessage.
		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods Ametys.data.ServerCaller#beforeServerCall and Ametys.data.ServerCaller#afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerComm#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerComm#callMethod cancelCode.
		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback beeing called with a null parameter. See Ametys.data.ServerComm#callMethod ignoreOnError.
		 */
		this.addCallables(
			{
				role: "org.ametys.odf.catalog.CatalogDAO",
	     		methodName: "editCatalog",
	     		callback: {
	         		handler: this._editCatalogCb
	     		},
	     		errorMessage: {
	     			msg: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_RENAME_RENAMEFAILED}}",
	     			category: Ext.getClassName(this)
	     		}
			}
		);
		
		/**
		 * @callable
		 * @member Ametys.odf.catalog.CatalogDAO
		 * @method removeCatalog 
		 * Removes an ODF catalog.
		 * This calls the method 'removeCatalog' of the server DAO 'CatalogDAO'.
		 * @param {Object[]} parameters The parameters to transmit to the server method
		 * @param {String} parameters[0] The id of the catalog to remove
		 * @param {Boolean} parameters[1] true to force deletion of catalog and remaining items in the catalog without requesting the user approval
		 * @param {Function} callback The function to call when the java process is over. Use options.scope for the scope. 
		 * @param {Object} callback.returnedValue The value return from the server. Null on error (please note that when an error occured, the callback may not be called depending on the value of errorMessage).
		 * @param {Object} callback.arguments Other arguments specified in option.arguments                 
		 * @param {Object} [options] Advanced options for the call.
		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerComm#callMethod errorMessage.
		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerComm#callMethod waitMessage.
		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods Ametys.data.ServerCaller#beforeServerCall and Ametys.data.ServerCaller#afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerComm#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerComm#callMethod cancelCode.
		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback beeing called with a null parameter. See Ametys.data.ServerComm#callMethod ignoreOnError.
		 */
		this.addCallables(
			{
			    role: "org.ametys.odf.catalog.CatalogDAO",
	     		methodName: "removeCatalog",
	     		callback: {
	         		handler: this._removeCatalogCb,
	         		scope: this
	     		},
	     		errorMessage: {
	     			msg: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_DELETEFAILED}}",
	     			category: Ext.getClassName(this)
	     		},
                localParamsIndex: 2
  			}
  		);
        
        /**
         * @callable
         * @member Ametys.odf.catalog.CatalogDAO
         * @method setDefaultCatalog 
         * Set a catalog as default catalog
         * This calls the method 'setDefaultCatalog' of the server DAO 'CatalogDAO'.
         * @param {Object[]} parameters The parameters to transmit to the server method
         * @param {String} parameters.id The id of the catalog to set a default
         * @param {Function} callback The function to call when the java process is over. Use options.scope for the scope. 
         * @param {Object} callback.returnedValue Null, there is no return value.
         * @param {Object} callback.arguments Other arguments specified in option.arguments                 
         * @param {Object} [options] Advanced options for the call.
         * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerComm#callMethod errorMessage.
         * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerComm#callMethod waitMessage.
         * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods Ametys.data.ServerCaller#beforeServerCall and Ametys.data.ServerCaller#afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
         * @param {Number} [options.priority] The message priority. See Ametys.data.ServerComm#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
         * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerComm#callMethod cancelCode.
         * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
         * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback beeing called with a null parameter. See Ametys.data.ServerComm#callMethod ignoreOnError.
         */
        this.addCallables(
            {
                role: "org.ametys.odf.catalog.CatalogDAO",
                methodName: "setDefaultCatalog",
                callback: {
                    handler: this._setDefaultCatalogCb
                },
                errorMessage: {
                    msg: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_SET_DEFAULT_ERROR}}",
                    category: Ext.getClassName(this)
                }
            }
        );
        
        /**
         * @callable
         * @member Ametys.odf.catalog.CatalogDAO
         * @method getDefaultCatalogName 
         * Get the default catalog's name
         * This calls the method 'getDefaultCatalogName' of the server DAO 'CatalogsManager'.
         * @param {Object[]} parameters The parameters to transmit to the server method
         * @param {Function} callback The function to call when the java process is over. Use options.scope for the scope. 
         * @param {Object} callback.defaultCatalogName The name of the default catalog or null if there is not default catalog 
         * @param {Object} callback.arguments Other arguments specified in option.arguments                 
         * @param {Object} [options] Advanced options for the call.
         * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerComm#callMethod errorMessage.
         * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerComm#callMethod waitMessage.
         * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods Ametys.data.ServerCaller#beforeServerCall and Ametys.data.ServerCaller#afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
         * @param {Number} [options.priority] The message priority. See Ametys.data.ServerComm#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
         * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerComm#callMethod cancelCode.
         * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
         * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback beeing called with a null parameter. See Ametys.data.ServerComm#callMethod ignoreOnError.
         */
        this.addCallables(
            {
                role: "org.ametys.odf.catalog.CatalogsManager",
                methodName: "getDefaultCatalogName",
                errorMessage: {
                    msg: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_GET_DEFAULT_ERROR}}",
                    category: Ext.getClassName(this)
                }
            }
        );
  		
  		/**
		 * @callable
		 * @member Ametys.odf.catalog.CatalogDAO
		 * @method getCatalogsProperties 
		 * Gets the properties of a catalog.
		 * This calls the method 'getCatalogProperties' of the server DAO 'CatalogDAO'.
		 * @param {Object[]} parameters The parameters to transmit to the server method
		 * @param {String} parameters.ids The ids of the catalogs to retrieve
		 * @param {Function} callback The function to call when the java process is over. Use options.scope for the scope. 
		 * @param {Object} callback.returnedValue The value return from the server. Null on error (please note that when an error occured, the callback may not be called depending on the value of errorMessage).
		 * @param {Object} callback.arguments Other arguments specified in option.arguments                 
		 * @param {Object} [options] Advanced options for the call.
		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerComm#callMethod errorMessage.
		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerComm#callMethod waitMessage.
		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods Ametys.data.ServerCaller#beforeServerCall and Ametys.data.ServerCaller#afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerComm#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerComm#callMethod cancelCode.
		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback beeing called with a null parameter. See Ametys.data.ServerComm#callMethod ignoreOnError.
		 */
		this.addCallables(
			{
			    role: "org.ametys.odf.catalog.CatalogDAO",
	     		methodName: "getCatalogsProperties",
	     		errorMessage: {
	     			msg: "{{i18n PLUGINS_ODF_CATALOG_DAO_GET_PROPERTIES_ERROR}}",
	     			category: Ext.getClassName(this)
	     		}
  			}
  		);
 	},
    
    /**
     * Get the catalog
     * @param {String} id The id of catalog
     * @param {Function} callback The callback function. Parameters are:
     */
    getCatalog: function (id, callback)
    {
        if (Ext.isEmpty(id))
        {
            callback(null);
            return;
        }
        this._getCatalogs ([id], Ext.bind(this._getCatalogCb, this, [callback], 1));
    },
    
    /**
     * @private
     * Callback function after calling #getCatalog
     * @param {Ametys.odf.catalog.Catalog[]} catalogs The resolved catalogs
     * @param {Function} callback The callback function
     */
    _getCatalogCb: function (catalogs, callback)
    {
        callback((catalogs.length == 0) ? null : catalogs[0]);
    },
    
    /**
     * Get catalogs
     * @param {String[]} ids The ids of catalog
     * @param {Function} callback The callback function. Parameters are:
     */
    getCatalogs: function (ids, callback)
    {
        if (Ext.isEmpty(ids))
        {
            callback([]);
            return;
        }
        this._getCatalogs (ids, Ext.bind(this._getCatalogsCb, this, [callback], 1));
    },
    
    /**
     * @private
     * Callback function after calling #getCatalogs
     * @param {Ametys.odf.catalog.Catalog[]} catalogs The resolved catalogs
     * @param {Function} callback The callback function
     */
    _getCatalogsCb: function (catalogs, callback)
    {
        callback(catalogs);
    },
        
    /**
     * Retrieve catalogs by doing a server request.
     * @param {String[]} ids Catalogs' identifiers
     * @param {Function} callback The callback function called after retrieving the catalog. Has the following parameters: 
     * @param {Ametys.odf.catalog.Catalog[]} callback.catalog An array of retrieved catalogs. Can be empty.
     * @param {Object} [scope=window] The callback scope, default to window. Can be null.
     * @private
     */
    _getCatalogs: function(ids, callback, scope)
    {
        ids = Ext.Array.from(ids);
        
        this.getCatalogsProperties([ids], this._sendGetCatalogRequestCb, {scope: this, arguments: [callback, scope]});
    },
    
    /**
     * Callback function called after #getCatalogsInformation is processed
     * @param {Object} response The response object.
     * @param {Array} args The callback arguments.
     * @param {Array} params The parameters.
     * @private
     */
    _sendGetCatalogRequestCb: function (response, args, params)
    {
        var callback = args[0] || Ext.emptyFn;
        var scope = args[1] || window;
        
        var catalogs = [];
        
        Ext.Array.forEach(response.catalogs, function(data) {
            catalogs.push(Ext.create ('Ametys.odf.catalog.Catalog', data));
        }, this);
        
        if (typeof callback == 'function')
        {
            callback (catalogs);
        }
    },
    
    /**
     * Get the store handling catalogs
     * @return {Ext.data.Store} the store handling catalogs
     */
    getStore: function()
    {
        if (!this._store)
        {
            this._store = Ext.create('Ext.data.Store', {
	            fields: [
                    {name: 'id'},
                    {name: 'isDefault'},
	                {name: 'code'},
                    {name: 'nbPrograms'},
	                {name: 'title', mapping: 'title', type: 'string'}
	            ],
	            sorters: {property: 'title', direction:'ASC'},
	            proxy: {
	                type: 'ametys',
	                plugin: 'odf',
	                url: 'catalogs.json',
	                reader: {
	                    type: 'json',
	                    rootProperty: 'catalogs'
	                }
	            },
	            autoLoad: true
	        });
        }
        return this._store;
    },
    
    /**
     * Creates a combo box mapped on catalogs' store #getStore
     * @param {Object} config The optional additional or personalized configuration object.
     * @param {Boolean} [config.synchronize=false] Set to `true`to synchronize this combo box field with the current active catalog.
     * @return {Ext.form.field.ComboBox} the combo box for catalogs.
     */
    createComboBox: function (config)
    {
        var cfg = config || {};
        var combo = Ext.create('Ext.form.field.ComboBox', Ext.applyIf(cfg, {
            cls: 'ametys',
            fieldLabel: "{{i18n PLUGINS_ODF_EXPORT_CATALOG_INDESIGN_DIALOGBOX_CATALOG}}",
            
            store: this.getStore(),
            
            valueField: 'code',
            displayField: 'title',
            
            queryMode: 'local',
            forceSelection : true,
            triggerAction: 'all'
        }));
        
        var onMessage = function(message) {
            var targets = message.getTargets(Ametys.message.MessageTarget.ODF_CATALOG);
            if (targets.length > 0)
            {
                this.getStore().load();
            }
        };
        
        Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, onMessage, combo);
        Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, onMessage, combo);
        Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, onMessage, combo);
        
        combo.on('destroy', function (combo) {Ametys.message.MessageBus.unAll(combo);});
        
        return combo;
    },
 	
 	/**
 	 * Callback function called after {@link #createCatalog} has been processed.
 	 * @param {Object} response The text response provided by the {@link Ametys.data.ServerComm}
 	 * @private
 	 */
 	_createCatalogCb: function(response)
 	{
		var message = response['message'];
		if (message == 'already-exist')
		{
            Ametys.notify({
                type: 'error',
                iconGlyph: 'odficon-book',
                title: "{{i18n PLUGINS_ODF_CATALOG_ADDCATALOGACTION_CREATION_SUCCESS_TITLE}}",
                description: "{{i18n PLUGINS_ODF_CATALOG_ADDCATALOGACTION_CREATION_ERROR_ALREADY_EXIST}}",
                action: Ext.bind(Ametys.tool.ToolsManager.openTool, Ametys.tool.ToolsManager, ['uitool-odf-catalogs', {}], false)
            });
		}
		else if (message == 'not-found')
		{
            Ametys.notify({
                type: 'error',
                iconGlyph: 'odficon-book',
                title: "{{i18n PLUGINS_ODF_CATALOG_ADDCATALOGACTION_CREATION_ERROR_TITLE}}",
                description: "PLUGINS_ODF_CATALOG_ADDCATALOGACTION_CREATION_ERROR_NOT_FOUND",
                action: Ext.bind(Ametys.tool.ToolsManager.openTool, Ametys.tool.ToolsManager, ['uitool-odf-catalogs', {}], false)
            });
		}
		else if (message == null)
		{
	    	Ext.create("Ametys.message.Message", {
	    		type: Ametys.message.Message.CREATED,
	    		targets: {
	    		    id: Ametys.message.MessageTarget.ODF_CATALOG,
	    			parameters: {
	    				id: response.id
	    			}
	    		}
	    	});
            
            Ametys.notify({
                type: 'info',
                iconGlyph: 'odficon-book',
                title: "{{i18n PLUGINS_ODF_CATALOG_ADDCATALOGACTION_CREATION_SUCCESS_TITLE}}",
                description: Ext.String.format("{{i18n PLUGINS_ODF_CATALOG_ADDCATALOGACTION_CREATION_SUCCESS}}", response.title),
                action: Ext.bind(Ametys.tool.ToolsManager.openTool, Ametys.tool.ToolsManager, ['uitool-odf-catalogs', {}], false)
            });
		}
 	},
 	
 	/**
 	 * Callback function called after {@link #editCatalog} has been processed.
 	 * @param {Object} response The text response provided by the {@link Ametys.data.ServerComm}
 	 * @private
 	 */
 	_editCatalogCb: function(response)
 	{
		var message = response['message'];
		if (message == 'not-found')
        {
            Ametys.Msg.show({
                   title: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_RENAME_ERROR_TITLE}}",
                   msg: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_RENAME_ERROR_NOT_FOUND}}",
                   buttons: Ext.Msg.OK,
                   icon: Ext.MessageBox.ERROR
            });
        }
        else if (message == null)
        {
			Ext.create("Ametys.message.Message", {
				type: Ametys.message.Message.MODIFIED,
				targets: {
				    id: Ametys.message.MessageTarget.ODF_CATALOG,
					parameters: {
						id: response.id
					}
				}
			});
        }
 	},
    
    /**
     * Callback function called after {@link #setDefaultCatalog} has been processed.
     * @param {Object} response The text response provided by the {@link Ametys.data.ServerComm}
     * @private
     */
    _setDefaultCatalogCb: function(response)
    {
        var message = response['message'];
        if (message == 'not-found')
        {
            Ametys.Msg.show({
                   title: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_SET_DEFAULT_ERROR_TITLE}}",
                   msg: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_SET_DEFAULT_ERROR_NOT_FOUND}}",
                   buttons: Ext.Msg.OK,
                   icon: Ext.MessageBox.ERROR
            });
        }
        else if (message == null)
        {
            Ext.create("Ametys.message.Message", {
                type: Ametys.message.Message.MODIFIED,
                targets: {
                    id: Ametys.message.MessageTarget.ODF_CATALOG,
                    parameters: {
                        id: response.id
                    }
                }
            });
        }
    },
 	
 	/**
     * @private
 	 * Callback function called after {@link #removeCatalog} has been processed.
 	 * @param {Object} response The response provided by the {@link Ametys.data.ServerComm}
     * @param {Object} args The callback arguments
     * @param {Object[]} params The parameters (server-side and client-side)
     * @param {String} params[0] the catalog's id
     * @param {boolean} params[1] true to force deletion without asking user approval if items remain in the catalog
     + @param {Ametys.message.MessageTarget} params[2] the target to delete
 	 */
 	_removeCatalogCb: function(response, _args, params)
 	{
	    var error = response['error'];
	    if (error)
	    {
            if (error == "remaining-items")
            {
                var remainingItems = response['remainingItems'];
                var message = "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_STILL_REFERENCED_1}}<ul>";
                if (remainingItems['program'] != null)
                {
                    message +="<li>" + remainingItems['program'] + " {{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_STILL_REFERENCED_PROGRAM}}</li>";
                }
                if (remainingItems['subProgram'] != null)
                {
                    message +="<li>" + remainingItems['subProgram'] + " {{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_STILL_REFERENCED_SUBPROGRAM}}</li>";
                }
                if (remainingItems['container'] != null)
                {
                    message +="<li>" + remainingItems['container'] + " {{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_STILL_REFERENCED_CONTAINER}}</li>";
                }
                if (remainingItems['courseList'] != null)
                {
                    message +="<li>" + remainingItems['courseList'] + " {{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_STILL_REFERENCED_COURSELIST}}</li>";
                }
                if (remainingItems['course'] != null)
                {
                    message +="<li>" + remainingItems['course'] + " {{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_STILL_REFERENCED_COURSE}}</li>";
                }
                if (remainingItems['coursePart'] != null)
                {
                    message +="<li>" + remainingItems['coursePart'] + " {{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_STILL_REFERENCED_COURSEPART}}</li>";
                }
                if (remainingItems['other'] != null)
                {
                    message +="<li>" + remainingItems['other'] + " {{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_STILL_REFERENCED_OTHER}}</li>";
                }
                message += "</ul>{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_STILL_REFERENCED_2}}";
                Ametys.Msg.show({
                    
                    icon: Ext.MessageBox.WARNING,
                    title: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_TITLE}}",
                    message: message,
                    buttons: Ext.MessageBox.YESNO,
                    fn: Ext.bind(this._confirmRemoveCatalogCb, this, [params[0], params[2]], 2),
                });
            }
            else if (error == "unknown-catalog")
            {
                Ametys.Msg.show({
                    title: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_TITLE}}",
                    msg: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_UNKNOWN_CATALOG}}",
                    buttons: Ext.MessageBox.OK,
                    icon: Ext.MessageBox.ERROR
                });
            }
            else
            {
                var message = response['message'];
                if (message)
                {
                    Ametys.Msg.show({
                    title: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_TITLE}}",
                    msg: message,
                    buttons: Ext.MessageBox.OK,
                    icon: Ext.MessageBox.ERROR
                });
                }
                else
                {
                    Ametys.Msg.show({
                        title: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_TITLE}}",
                        msg: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_ERROR_DELETEFAILED}}",
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.ERROR
                    });
                }
            }
        }
        else
        {
            // The scheduler was fired
            Ametys.notify({
                type: 'info',
                iconGlyph: 'odficon-book',
                title: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_SCHEDULABLE_FIRED_TITLE}}",
                description: Ext.String.format("{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_SCHEDULABLE_FIRED}}", params[2].getParameters().title),
                action: Ext.bind(Ametys.tool.ToolsManager.openTool, Ametys.tool.ToolsManager, ['uitool-odf-catalogs', {}], false)
            });
            // we initiate a loop to check regularly if the task is over
            this._waitForEndOfCatalogRemovalAndNotify(response['jobId'], params[2]);
	    }
	 },
	 
	 _confirmRemoveCatalogCb: function(btn, _text, catalogId, target)
	 {
        if (btn == "yes")
        {
            this.removeCatalog([catalogId, true, target]);
        }
     },
     
     /**
      * @private
      * Regulary ping the server to check if the removal is completed
      * @param target the target being deleted
      */
     _waitForEndOfCatalogRemovalAndNotify: function(jobId, target)
     {
        var me = this;
        setTimeout( function() {
             Ametys.plugins.core.schedule.Scheduler.getTasksInformation(
                [[jobId]],
                me._waitForEndOfCatalogRemovalAndNotifyCb,
                {
                    scope: me,
                    arguments: {jobId: jobId, target: target}
                }
            )},
            5000
        );
    },
    
    /**
     * @private
     * Check if the job is still running.
     * If not, notify of the catalog removal
     * @param response the server response. See Scheduler#getTaskInformation for more details.
     * @param args the argument provided by the caller
     * @param args.jobId the job id
     * @param args.target the target being removed
     */
    _waitForEndOfCatalogRemovalAndNotifyCb: function(response, args)
    {
        var jobId = args.jobId;
        var target = args.target;
        var state = response[0].getState();
        if (state == "running" || state == "waiting")
        {
            this._waitForEndOfCatalogRemovalAndNotify(jobId, target);
        }
        else if (state == "success")
        {
            Ametys.notify({
                type: 'info',
                iconGlyph: 'odficon-book',
                title: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_SCHEDULABLE_SUCCESS_TITLE}}",
                description: Ext.String.format("{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_SCHEDULABLE_SUCCESS}}", target.getParameters().title),
                action: Ext.bind(Ametys.tool.ToolsManager.openTool, Ametys.tool.ToolsManager, ['uitool-odf-catalogs', {}], false)
            });
            Ext.create("Ametys.message.Message", {
                type: Ametys.message.Message.DELETED,
                targets: target
            });
        }
        else if (state == "failure")
        {
            Ametys.notify({
                type: 'error',
                iconGlyph: 'odficon-book',
                title: "{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_SCHEDULABLE_FAILURE_TITLE}}",
                description: Ext.String.format("{{i18n PLUGINS_ODF_CATALOG_CATALOGACTIONS_DELETE_SCHEDULABLE_FAILURE}}", target.getParameters().title),
                action: Ext.bind(Ametys.tool.ToolsManager.openTool, Ametys.tool.ToolsManager, ['uitool-odf-catalogs', {}], false)
            });
        }
    }
 });