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

/**
 * DAO for manipulating directory link
 */
Ext.define("Ametys.plugins.linkdirectory.link.LinkDAO", {
    singleton: true,
    
    constructor: function()
    {
    	/**
		 * @callable
		 * @member Ametys.plugins.linkdirectory.link.LinkDAO
		 * @method createLink 
		 * This calls the method 'createLink' of the server DAO 'org.ametys.plugins.linkdirectory.link.LinkDAO'.
		 * Create a new link.
		 * @param {Object[]} parameters The parameters to transmit to the server method are:
		 * @param {String} parameters.values The data of link to create
		 * @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.plugins.linkdirectory.link.LinkDAO",
				methodName: "createLink",
				callback: {
	         		handler: this._createLinkCb
	     		},
	     		waitMessage: true,
				errorMessage: {
				    msg: "{{i18n PLUGINS_LINKDIRECTORY_LINK_ERROR_CREATE}}",
				    category: Ext.getClassName(this)
				}
			}
		);
		
		/**
		 * @callable
		 * @member Ametys.plugins.linkdirectory.link.LinkDAO
		 * @method updateLink 
		 * This calls the method 'updateLink' of the server DAO 'org.ametys.plugins.linkdirectory.link.LinkDAO'.
		 * Update a link
		 * @param {Object[]} parameters The parameters to transmit to the server method are:
		 * @param {String} parameters.values The data of link to create
		 * @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.plugins.linkdirectory.link.LinkDAO",
				methodName: "updateLink",
				callback: {
	         		handler: this._updateLinkCb
	     		},
	     		waitMessage: true,
				errorMessage: {
				    msg: "{{i18n PLUGINS_LINKDIRECTORY_LINK_ERROR_EDIT}}",
				    category: Ext.getClassName(this)
				}
			}
		);
		
		/**
		 * @callable
		 * @member Ametys.plugins.linkdirectory.link.LinkDAO
		 * @method deleteLinks 
		 * This calls the method 'deleteLinks' of the server DAO 'org.ametys.plugins.linkdirectory.link.LinkDAO'.
		 * Delete links
		 * @param {Object[]} parameters The parameters to transmit to the server method are:
		 * @param {String} parameters.ids The id of links to delete
		 * @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.plugins.linkdirectory.link.LinkDAO",
				methodName: "deleteLinks",
				callback: {
	         		handler: this._deleteLinksCb
	     		},
	     		waitMessage: true,
				errorMessage: {
				    msg: "{{i18n PLUGINS_LINKDIRECTORY_LINK_ERROR_DELETE}}",
				    category: Ext.getClassName(this)
				},
				localParamsIndex: 1
			}
		);
		
		/**
		 * @callable
		 * @member Ametys.plugins.linkdirectory.link.LinkDAO
		 * @method moveLink 
		 * This calls the method 'moveLink' of the server DAO 'org.ametys.plugins.linkdirectory.link.LinkDAO'.
		 * Move a link
		 * @param {Object[]} parameters The parameters to transmit to the server method are:
		 * @param {String} parameters.id The id of link to move
		 * @param {String} role The mode of move. Accepted values are: 'up', 'down', 'first' or 'last'
		 * @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.plugins.linkdirectory.link.LinkDAO",
				methodName: "moveLink",
				callback: {
	         		handler: this._moveLinkCb
	     		},
	     		waitMessage: true,
				errorMessage: {
				    msg: "{{i18n PLUGINS_LINKDIRECTORY_HANDLE_MOVE_LINK_ERROR}}",
				    category: Ext.getClassName(this)
				}
			}
		);
		
		/**
		 * @callable
		 * @member Ametys.plugins.linkdirectory.link.LinkDAO
		 * @method getLinks 
		 * This calls the method 'getLinks' of the server DAO 'org.ametys.plugins.linkdirectory.link.LinkDAO'.
		 * @param {Object[]} parameters The parameters to transmit to the server method are:
		 * @param {String} parameters.ids The id of links to retrieve
		 * @param {Function} callback The function to call when the java process is over. Use options.scope for the scope. 
		 * @param {Ametys.plugins.linkdirectory.link.Link[]} callback.links The retrieved links. 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.args 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.plugins.linkdirectory.link.LinkDAO",
				methodName: "getLinks",
				convertor: this._convertLinks,
	     		waitMessage: false,
				errorMessage: {
				    msg: "{{i18n PLUGINS_LINKDIRECTORY_GET_LINK_ERROR}}",
				    category: Ext.getClassName(this)
				}
			}
		);
		
		/**
		 * @callable
		 * @member Ametys.plugins.linkdirectory.link.LinkDAO
		 * @method getLink 
		 * This calls the method 'getLink' of the server DAO 'org.ametys.plugins.linkdirectory.link.LinkDAO'.
		 * @param {Object[]} parameters The parameters to transmit to the server method are:
		 * @param {String} parameters.id The id of link to retrieve
		 * @param {Function} callback The function to call when the java process is over. Use options.scope for the scope. 
		 * @param {Ametys.plugins.linkdirectory.link.Link} callback.link The link. 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.plugins.linkdirectory.link.LinkDAO",
				methodName: "getLink",
				convertor: this._convertLink,
	     		waitMessage: false,
				errorMessage: {
				    msg: "{{i18n PLUGINS_LINKDIRECTORY_GET_LINK_ERROR}}",
				    category: Ext.getClassName(this)
				}
			}
		);
		
		/**
		 * @callable
		 * @member Ametys.plugins.linkdirectory.link.LinkDAO
		 * @method isInternalURLAllowed 
		 * This calls the method 'isInternalURLAllowed' of the server DAO 'org.ametys.plugins.linkdirectory.link.LinkDAO'.
		 * @param {Object[]} parameters The parameters to transmit to the server method are:
		 * @param {String} parameters.siteName The site name
		 * @param {Function} callback The function to call when the java process is over. Use options.scope for the scope. 
		 * @param {Boolean} callback.allowedInternalUrl True if internal URL are allowed. 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.args 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.plugins.linkdirectory.link.LinkDAO",
				methodName: "isInternalURLAllowed",
	     		waitMessage: false,
				errorMessage: true
			}
		);
        
        /**
         * @callable
         * @member Ametys.plugins.linkdirectory.link.LinkDAO
         * @method getDynamicInformationProviders 
         * This calls the method 'getDynamicInformationProviders' of the server DAO 'org.ametys.plugins.linkdirectory.link.LinkDAO'.
         * @param {Function} callback The function to call when the java process is over. Use options.scope for the scope. 
         * @param {Object[]} callback.dynamicInformationProviders The providers of dynamic information.
         * @param {Object} callback.args 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.plugins.linkdirectory.link.LinkDAO",
                methodName: "getDynamicInformationProviders",
                waitMessage: false,
                errorMessage: true
            }
        );
    },
    
    /**
     * @private
     * Extract and convert links' configuration received from server.
     * @param {Object} linkConfigs The configuration objects. Null on error (please note that when an error occurred, the callback may not be called depending on the value of errorMessage).
     * @param {Object} args Other arguments specified in option.arguments            
     * @param {Object} parameters Parameters of the initial call transmited in parameters argument.
     * @return {Ametys.plugins.linkdirectory.link.Link[]} the links
     */
    _convertLinks: function (linkConfigs, args, parameters)
    {
    	var links = [];
    	
    	if (linkConfigs)
    	{
    		for (var i=0; i < linkConfigs.length; i++)
    		{
        		links.push(Ext.create ('Ametys.plugins.linkdirectory.link.Link', linkConfigs[i]));
    		}
    	}
    	
    	return links;
    },
    
    /**
     * @private
     * Extract and convert link's configuration received from server.
     * @param {Object} linkConfig The configuration object. Null on error (please note that when an error occurred, the callback may not be called depending on the value of errorMessage).
     * @param {Object} args Other arguments specified in option.arguments            
     * @param {Object} parameters Parameters of the initial call transmited in parameters argument.
     * @return {Ametys.plugins.linkdirectory.link.Link} the link
     */
    _convertLink: function (linkConfig, args, parameters)
    {
    	if (linkConfig && linkConfig.id)
    	{
    		return Ext.create ('Ametys.plugins.linkdirectory.link.Link', linkConfig);
    	}
    	else
    	{
    		return null;
    	}
    },

    /**
     * Callback function invoked after creating a link
     * @param {Object} response the server response
     * @param {Object} args The callback arguments
     */
    _createLinkCb: function(response, args)
    {
        if (response['already-exists'])
        {
        	 Ametys.Msg.show({
                 title: "{{i18n PLUGINS_LINKDIRECTORY_LINK_ADD_TITLE}}",
                 msg: "{{i18n PLUGINS_LINKDIRECTORY_LINK_ERROR_ALREADY_EXISTS}}",
                 buttons: Ext.Msg.OK,
                 icon: Ext.MessageBox.ERROR
        	 });
        	 return;
        }
        
        var link = Ext.create('Ametys.plugins.linkdirectory.link.Link', response);

        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.CREATED,
            
            targets: {
                id: Ametys.message.MessageTarget.LINK_DIRECTORY,
                parameters: { links: [link] }
            }
        });
    },
    
    /**
     * Callback function invoked after updating a link
     * @param {Object} response the server response
     * @param {Object} args The callback arguments
     */
    _updateLinkCb: function(response, args)
    {
        if (response['already-exists'])
        {
        	 Ametys.Msg.show({
                 title: "{{i18n PLUGINS_LINKDIRECTORY_LINK_EDIT_TITLE}}",
                 msg: "{{i18n PLUGINS_LINKDIRECTORY_LINK_ERROR_ALREADY_EXISTS}}",
                 buttons: Ext.Msg.OK,
                 icon: Ext.MessageBox.ERROR
        	 });
        	 return;
        }
        
        if (response['unknown-link'])
        {
        	Ametys.Msg.show({
                title: "{{i18n PLUGINS_LINKDIRECTORY_LINK_EDIT_TITLE}}",
                msg: "{{i18n PLUGINS_LINKDIRECTORY_LINK_ERROR_UNKNOWN}}",
                buttons: Ext.Msg.OK,
                icon: Ext.MessageBox.ERROR
            });
        	 return;
        }
        
        var link = Ext.create('Ametys.plugins.linkdirectory.link.Link', response);

        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.MODIFIED,
            
            targets: {
                id: Ametys.message.MessageTarget.LINK_DIRECTORY,
                parameters: { links: [link] }
            }
        });
    },
    
    /**
     * @private
     * Callback function invoked after deleting links
     * @param {String[]} ids the id of deleted links
     * @param {Object} args The callback arguments
     * @param {Object[]} params The parameters (server-side and client-side)
     * @param {String[]} params.ids The ids of deleted links
     * @param {Ametys.message.MessageTarget[]} params.targets The deleted targets
     */
    _deleteLinksCb: function(ids, args, params)
    {
        if (ids && ids.length > 0)
        {
        	Ext.create('Ametys.message.Message', {
                type: Ametys.message.Message.DELETED,
                
                targets: params[1]
            });
        }
    },
    
    /**
     * Callback function invoked after moving a link
     * @param {Object} response the server's response
     * @param {String[]} response.id the id of moved link
     * @param {Object} args The callback arguments
     */
    _moveLinkCb: function(response, args)
    {
        if (response && response.id)
        {
        	var link = Ext.create('Ametys.plugins.linkdirectory.link.Link', response);

            Ext.create('Ametys.message.Message', {
                type: Ametys.message.Message.MOVED,
                
                targets: {
                    id: Ametys.message.MessageTarget.LINK_DIRECTORY,
                    parameters: { links: [link] }
                }
            });
        }
    }
});