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

/**
 * Helper for skin edition.
 */
Ext.define('Ametys.plugins.skincommons.helper.SkinHelper', {
    singleton: true,

    /**
     * Get the skin model attached to a skin
	 * @param {String} serverRole The role of skin component
     * @param {String} siteName The site name. Can be null if skinName is not null.
     * @param {String} skinName The skin name. Can be null if siteName is not null.
     * @param {String} mode the edition mode: 'temp', 'work' or null
     * @param {Function} callback The callback. Parameters are:
     * @param {String} callback.skinName the skin name
     * @param {String} callback.modelName the model linked to this skin or null if there is linked model.
     */
    getSkinModel : function (serverRole, siteName, skinName, mode, callback)
    {
        var params = {};
        params.siteName = siteName;
        params.skinName = skinName;

        Ametys.data.ServerComm.callMethod({
            role: serverRole,
            methodName: "getSkinModel",
            parameters: [siteName, skinName, mode],
            callback: {
                handler: this._getSkinModelCb, 
                scope: this, 
                arguments: { "callback" : callback, "skinName" : skinName }
            },
            errorMessage: {
                msg: "{{i18n PLUGINS_SKINCOMMONS_GETMODEL_ERROR}}",
                category: "Ametys.plugins.skincommons.helper.getSkinModel"
            },
            waitMessage: true
        });
    },

    /**
     * Callback invoked after getting the skin model
     * @param {String} modelName The model's name. Can be null if no model is linked to this skin.
     * @param {Object} args The callback arguments
     * @private
     */
    _getSkinModelCb: function (modelName, args)
    {
        if (Ext.isFunction(args.callback))
        {
            args.callback(args.skinName, modelName);
        }
    },

    // ----------------------------------------------------------------
    /**
     * Get lock information
	 * @param {String} serverRole The role of skin component
     * @param {String} siteName The site name. Can be null if skinName is not null.
     * @param {String} skinName The skin name. Can be null if siteName is not null.
     * @param {Function} callback The callback function
     * @param {Object} callback.lockInfos Informations on lock status
     */
    getLockParams : function (serverRole, siteName, skinName, callback)
    {
        Ametys.data.ServerComm.callMethod({
            role: serverRole,
            methodName: "getLock",
            parameters: [siteName, skinName],
            callback: {
                handler: this._getLockParamsCb, 
                scope: this, 
                arguments: { "callback" : callback, "skinName" : skinName }
            },
            errorMessage: {
                msg: "{{i18n PLUGINS_SKINCOMMONS_CHECKLOCK_ERROR}}",
                category: "Ametys.plugins.skincommons.helper.getLockParams"
            },
            waitMessage: true
        });
     },

     /**
      * Callback for the {#getLockParams} method
      * @param {Object} response the server response
      * @param {Object} args Callback arguments
      * @private
      */
     _getLockParamsCb: function(response, args)
     {
        var lockParams = {};
        lockParams.isLocked = response.isLocked;
        
        if (response.lockOwner)
        {
        	lockParams.lockOwner = response.lockOwner;
        	lockParams.lockDate = Ext.util.Format.date(Ext.Date.parseDate(response.lastModified, Ext.Date.patterns.ISO8601DateTime), "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_DATEFORMAT}}");
        }
        
        var lastSave = response.lastSave;
        if (response.lastSave)
        {
            lockParams.lastSave = Ext.util.Format.date(Ext.Date.parseDate(response.lastSave, Ext.Date.patterns.ISO8601DateTime), "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_DATEFORMAT}}")
        }
        
        if (Ext.isFunction(args.callback))
        {
            args.callback(lockParams);
        }
    },
    
    /**
     * Display error message if the skin is currently locked by another user
     * @param {Object} result The server result
     * @param {Boolean} result.isLocked true if the skin is locked.
     * @return {Boolean} true if the result is locked
     */
    handleLockError: function (result)
    {
        if (result != null && result.isLocked)
        {
            Ametys.Msg.show({
                title: "{{i18n PLUGINS_SKINCOMMONS_LOCK_ERROR_TITLE}}",
                msg: "{{i18n PLUGINS_SKINCOMMONS_LOCK_ERROR_HINT_1}}" + result.lockOwner + "{{i18n PLUGINS_SKINCOMMONS_LOCK_ERROR_HINT_2}}",
                buttons: Ext.Msg.OK,
                icon: Ext.MessageBox.ERROR
            });
            return true;
        }

        return false;
    },


    //----------------------------------------------------------------
    /**
     * Check if there is unsaved or uncommitted modifications before quit
	 * @param {String} serverRole The role of skin component
     * @param {String} skinName The skin name
     * @param {Function} callback The callback function
     */
    checkUnsaveModification : function (serverRole, skinName, callback)
    {
    	Ametys.data.ServerComm.callMethod({
            role: serverRole,
            methodName: "checkUnsaveModifications",
            parameters: [skinName],
            callback: {
                handler: this._checkUnsaveModification,
                scope: this,
                arguments: {
                    callback: callback,
                    skinName: skinName,
					serverRole: serverRole
                }
            },
            errorMessage:
            {
                msg: "{{i18n PLUGINS_SKINCOMMONS_CHECK_UNSAVE_ERROR}}",
                category: this.self.getName()
            },
            waitMessage: true
        });
    },

    /**
     * @private
     * Callback from server when checking for unsaved modifications
     * @param {Object} response The xml http response
     * @param {Object} args The client side args
     * @param {String} args.skinName The name of the skin
     * @param {Function} args.callback The function to callback at the end
     */
    _checkUnsaveModification: function (response, args)
    {
    	if (response.hasUncommitedChanges)
    	{
    		this.openUncommitChangesDialog (args.serverRole, args.skinName, args.callback);
    	}
    	else if (response.hasUnsaveChanges)
    	{
    		this.openUnsaveModificationsDialog (args.serverRole, args.skinName, args.callback);
    	}
    	else if (Ext.isFunction(args.callback))
        {
        	args.callback (true);
        }
    },
    
    // ----------------------------------------------------------------------
    /**
     * Open dialog box for uncommited changes
	 * @param {String} serverRole The role of skin component
     * @param {String} skinName The editing skin name
     * @param {Function} callback The callback function
     */
    openUncommitChangesDialog : function (serverRole, skinName, callback) 
    {
        if (this._uncommitChangesBox == null)
        {
        	var form = new Ext.form.FormPanel({
                border: false,
                scrollable: true,
                defaults: {
                    cls: 'ametys',
                    anchor: '95%',
                    labelAlign: 'right',
                    labelSeparator: '',
                    labelWidth: 50
                },
                items: [
                    {
                        xtype: 'container',
                        cls: 'text', 
                        html: "{{i18n PLUGINS_SKINCOMMONS_CLOSE_TOOL_NO_COMMITED_MODIFICATION_HINT}}"
                    },
                    {
                        xtype: 'radio',
                        hideLabel: true, 
                        itemCls: 'checkbox', 
                        boxLabel: "{{i18n PLUGINS_SKINCOMMONS_CLOSE_TOOL_NO_COMMITED_MODIFICATION_CHOICE_KEEP}}", 
                        name: 'choice', 
                        inputValue: "keep", 
                        checked: true
                    },
                    {
                        xtype: 'radio', 
                        hideLabel: true,
                        itemCls: 'checkbox',
                        boxLabel: "{{i18n PLUGINS_SKINCOMMONS_CLOSE_TOOL_NO_COMMITED_MODIFICATION_CHOICE_COMMIT}}", 
                        name: 'choice', 
                        inputValue: "commit"
                    },
                    {
                        xtype: 'radio', 
                        hideLabel: true,
                        itemCls: 'checkbox',
                        boxLabel: "{{i18n PLUGINS_SKINCOMMONS_CLOSE_TOOL_NO_COMMITED_MODIFICATION_CHOICE_CLEAR}}", 
                        name: 'choice', 
                        inputValue: "clear-work"
                    }
                ]
            });
            
            this._uncommitChangesBox = new org.ametys.DialogBox({
                
                title :"{{i18n PLUGINS_SKINCOMMONS_CLOSE_TOOL_NO_COMMITED_MODIFICATION_TITLE}}",
                iconCls : 'ametysicon-save31',
                
                border: false,
                width : 500,
                
                items: [form],
                
                closeAction: 'hide',
                buttons : [{
                           		text :"{{i18n PLUGINS_SKINCOMMONS_CANCELCHANGES_DIALOG_OK_BTN}}"
	                       }, {
	                            text :"{{i18n PLUGINS_SKINCOMMONS_CANCELCHANGES_DIALOG_CANCEL_BTN}}",
	                       } 
                ]
            });
        }
        
        var buttons = this._uncommitChangesBox.getDockedItems('toolbar[dock="bottom"]')[0];	
        buttons.items.get(0).setHandler(Ext.bind (this._validateUncommitChanges, this, [serverRole, skinName, callback]));
        buttons.items.get(1).setHandler(Ext.bind (this._cancelUncommitChanges, this, [callback]));
        
        this._uncommitChangesBox.show();
    },

    /**
     * Function called when validating dialog box
	 * @param {String} serverRole The role of skin component
     * @param {String} skinName The editing skin name
     * @param {Function} callback the callback function
     * @private
     */
    _validateUncommitChanges : function(serverRole, skinName, callback)
    {
    	var form = this._uncommitChangesBox.items.get(0).getForm();
        var choice = form.findField('choice').getGroupValue();
        
        if (choice == 'commit')
        {
            this._uncommitChangesBox.hide();
            Ametys.plugins.skincommons.CommonSkinActions.commitChanges (serverRole, skinName, true, Ext.bind(this._validateUncommitChangesCb, this, [callback], true));
        }
        else
        {
        	var workVersion = choice == 'clear-work';
        	Ametys.plugins.skincommons.CommonSkinActions.clearModifications (serverRole, skinName, workVersion, Ext.bind(this._validateUncommitChangesCb, this, [callback], true));
        }
    },

    /**
     * Callback function invoked after commiting changes
     * @param {Boolean} success true if the operation was successful
     * @param {Function} callback callback function
     * @private
     */
    _validateUncommitChangesCb : function (success, callback)
    {
    	if (success)
    	{
    		this._uncommitChangesBox.hide();
    	}
    	
        if (Ext.isFunction (callback))
        {
        	callback (success);
        }
    },

    /**
     * Action called when clicking on 'cancel' button
     * @param {Function} callback callback function
     * @private
     */
    _cancelUncommitChanges : function(callback)
    {
    	this._uncommitChangesBox.hide();
        
        if (Ext.isFunction(callback))
        {
        	callback(false);
        }
    },
    
    // ----------------------------------------------------------------------
	/**
     * Open dialog box for unsaved changes
	 * @param {String} serverRole The role of skin component
     * @param {String} skinName The editing skin name
     * @param {Function} callback The callback function
     */
    openUnsaveModificationsDialog : function (serverRole, skinName, callback) 
    {
    	if (this._unsaveChangesBox == null)
    	{
	        var form = Ext.create ('Ext.form.FormPanel', {
                border: false,
                scrollable: true,
                defaults: {
                    cls: 'ametys',
                    anchor: '95%',
                    labelAlign: 'right',
                    labelSeparator: '',
                    labelWidth: 50
                },

	            items: [
                    {
                        xtype: 'container', 
                        cls: 'hint', 
                        html: "{{i18n PLUGINS_SKINCOMMONS_CLOSE_TOOL_NO_SAVED_MODIFICATION_HINT}}"
                    },
                    {
                        xtype: 'radio',
                        hideLabel: true,
                        itemCls: 'checkbox', 
                        boxLabel: "{{i18n PLUGINS_SKINCOMMONS_CLOSE_TOOL_NO_SAVED_MODIFICATION_CHOICE_SAVE}}", 
                        name: 'choice',
                        itemId: 'choice',
                        inputValue: "save", 
                        checked:true
                    },
                    {
                        xtype: 'radio',
                        hideLabel: true,
                        itemCls: 'checkbox', 
                        boxLabel: "{{i18n PLUGINS_SKINCOMMONS_CLOSE_TOOL_NO_SAVED_MODIFICATION_CHOICE_COMMIT}}", 
                        name: 'choice', 
                        inputValue: "commit"
                    },
                    {
                        xtype: 'radio',
                        hideLabel: true,
                        itemCls: 'checkbox', 
                        boxLabel: "{{i18n PLUGINS_SKINCOMMONS_CLOSE_TOOL_NO_SAVED_MODIFICATION_CHOICE_CLEAR}}", 
                        name: 'choice', 
                        inputValue: "clear-temp"
                    }
	            ]
	        });
	        
	        this._unsaveChangesBox = Ext.create('Ametys.window.DialogBox', {
	            
	            title :"{{i18n PLUGINS_SKINCOMMONS_CLOSE_TOOL_NO_SAVED_MODIFICATION_TITLE}}",
	            iconCls : 'ametysicon-save31',
	            
	            border: false,
	            width : 500,
	            layout: "fit",
	            
	            items: [form],
	            
	            defaultFocus: 'choice',
	            closeAction: 'hide',
	            referenceHolder: true,
	            defaultButton: 'validate',
	            
	            buttons: [{
	                	reference: 'validate',
	                    text :"{{i18n PLUGINS_SKINCOMMONS_CANCELCHANGES_DIALOG_OK_BTN}}"
	                }, {
	                    text :"{{i18n PLUGINS_SKINCOMMONS_CANCELCHANGES_DIALOG_CANCEL_BTN}}"
                }]
	        });
    	}
    	
        var buttons = this._unsaveChangesBox.getDockedItems('toolbar[dock="bottom"]')[0];	
        buttons.items.get(0).setHandler(Ext.bind (this._validateUnsaveChanges, this, [serverRole, skinName, callback]));
        buttons.items.get(1).setHandler(Ext.bind (Ext.bind (this._cancelUnsaveChanges, this, [callback])));
        
    	this._unsaveChangesBox.show();
    },

    /**
     * Function invoked when clicking 'ok' button
	 * @param {String} serverRole The role of skin component
     * @param {String} skinName The skin name
     * @param {Function} callback the callback function
     * @private
     */
    _validateUnsaveChanges : function(serverRole, skinName, callback)
    {
    	var form = this._unsaveChangesBox.items.get(0).getForm();
        var choice = form.findField('choice').getGroupValue();
        
        if (choice == 'save')
        {
            Ametys.plugins.skincommons.CommonSkinActions.saveChanges (serverRole, skinName, true, Ext.bind(this._validateUnsaveChangesCb, this, [callback], true));
        }
        else if (choice == 'commit')
        {
            Ametys.plugins.skincommons.CommonSkinActions.commitChanges (serverRole, skinName, true, Ext.bind(this._validateUnsaveChangesCb, this, [callback], true));
        }
        else if (choice == 'clear-temp')
        {
        	Ametys.plugins.skincommons.CommonSkinActions.clearModifications (serverRole, skinName, false, Ext.bind(this._validateUnsaveChangesCb, this, [true, callback], true));
        }
    },

    /**
     * Callback invoked after validating dialog box
     * @param {Boolean} success true if the operation succeed
     * @param {Boolean} quit true if the user wants to quit the tool
     * @param {Function} callback the callback function
     * @private
     */
    _validateUnsaveChangesCb : function (success, quit, callback)
    {
    	if (success)
    	{
    		this._unsaveChangesBox.hide();
    	}
    	
        if (Ext.isFunction (callback))
        {
        	callback (success, quit);
        }
    },

    /**
     * Action called when clicking on 'cancel' button
     * @param {Function} callback callback function
     * @private
     */
    _cancelUnsaveChanges : function(callback)
    {
    	this._unsaveChangesBox.hide();
        
        if (Ext.isFunction(callback))
        {
        	callback(false);
        }
    },
    
    // ----------------------------------------------------------------------
	/**
     * Open dialog box for cancel changes
	 * @param {String} serverRole The role of skin component
     * @param {String} skinName The editing skin name
     * @param {String} toolId The current tool id
     * @param {Function} callback The callback function
     */
    openCancelModificationsDialog : function (serverRole, skinName, toolId, callback) 
    {
    	if (this._cancelChangesBox == null)
    	{
	    	var form = Ext.create('Ext.form.FormPanel', {
	            border: false,
	            scrollable: true,
	            defaults: {
	                cls: 'ametys',
	                anchor: '95%',
	                labelAlign: 'right',
	                labelSeparator: '',
	                labelWidth: 50
	            },
	            
	            items: [{
		                xtype: 'container',
		                cls: 'text',
		                html: "{{i18n PLUGINS_SKINCOMMONS_CANCELCHANGES_CHOICE_LABEL}}"
		            }, {
		            	xtype: 'radio',
		                hideLabel: true,
		                itemCls: 'checkbox',
		                boxLabel: "{{i18n PLUGINS_SKINCOMMONS_CANCELCHANGES_CHOICE_1}}",
		                name: 'workVersion',
		                itemId: 'workVersion',
		                inputValue: true,
		                checked: true
		            }, {
		            	xtype: 'radio',
		                hideLabel: true,
		                itemCls: 'checkbox',
		                boxLabel: "{{i18n PLUGINS_SKINCOMMONS_CANCELCHANGES_CHOICE_2}}",
		                name: 'workVersion',
		                inputValue: false
		            }
	            ]
	    	});
	    	
	    	this._cancelChangesBox = Ext.create('Ametys.window.DialogBox', {
	            
	    		title: "{{i18n PLUGINS_SKINCOMMONS_CANCELCHANGES_TITLE}}",
	            iconCls: 'ametysicon-save31 decorator-ametysicon-delete30',
	            
	            border: false,
	            width : 500,
                
	            items: [form],
	            
	            defaultFocus: 'workVersion',
	            closeAction: 'hide',
	            referenceHolder: true,
	            defaultButton: 'validate',
	            
	            buttons: [{
	                	reference: 'validate',
	                    text :"{{i18n PLUGINS_SKINCOMMONS_CANCELCHANGES_DIALOG_OK_BTN}}"
	                }, {
	                    text :"{{i18n PLUGINS_SKINCOMMONS_CANCELCHANGES_DIALOG_CANCEL_BTN}}"
	                } 
	            ]
	        });
    	}
    	
        var buttons = this._cancelChangesBox.getDockedItems('toolbar[dock="bottom"]')[0];	
        buttons.items.get(0).setHandler(Ext.bind (this._validateCancelChanges, this, [serverRole, skinName, toolId, callback]));
        buttons.items.get(1).setHandler(Ext.bind (this._cancelCancelChanges, this, [callback]));

    	this._cancelChangesBox.show();
    },
    
    /**
     * Function invoked when clicking 'ok' button
	 * @param {String} serverRole The role of skin component
     * @param {String} skinName The skin name
     * @param {String} toolId The tool's id
     * @param {Function} callback the callback function
     * @private
     */
    _validateCancelChanges: function (serverRole, skinName, toolId, callback)
    {
    	var form = this._cancelChangesBox.items.get(0).getForm();
    	var workVersion = form.getValues().workVersion;
    	
    	Ametys.plugins.skincommons.CommonSkinActions.cancelChanges (serverRole, skinName, workVersion, toolId, Ext.bind(this._validateCancelChangesCb, this, [callback], true));
    },
    
    /**
     * Callback invoked after cancelling changes
     * @param {Boolean} success true if the operation succeed
     * @param {Function} callback the callback function
     * @private
     */
    _validateCancelChangesCb : function (success, callback)
    {
    	if (success)
    	{
    		this._cancelChangesBox.hide();
    	}
    	
        if (Ext.isFunction (callback))
        {
        	callback (success);
        }
    },
    
    /**
     * Action called when clicking on 'cancel' button
     * @param {Function} callback callback function
     * @private
     */
    _cancelCancelChanges : function(callback)
    {
    	this._cancelChangesBox.hide();
        
        if (Ext.isFunction(callback))
        {
        	callback(false);
        }
    }
});