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

/**
 * This helper is used to import a skin from a ZIP file. See #open method.
 */
Ext.define("Ametys.plugins.web.skin.helper.ImportSkinUI", {
    singleton: true,

    /**
     * @private
     * @property {Function} _cbFn Callback function to execute after import
     */

    /**
     * @private
     * @property {Ametys.window.DialogBox} _box The dialog box
     */

    /**
     * @private
     * @property {Ext.form.FormPanel} _formPanel The form of the dialog box
     */

    /**
     * Open the dialog box for import
     * @param {Object} config The configuration object
     * @param {String} config.url (required) The url to submit form
     * @param {Function} config.importFn (required) The function to do import. Parameters are: 
     * @param {Object} config.importFn.result The import result
     * @param {Object} config.importFn.box The import dialog box
     * @param {String} [config.importErrorMsg] The error message in case of failure
     * @param {Function} [config.existFn] A function to test existence of a file to upload. Parameters are: 
     * @param {String[]} config.existFn.params Array of parameters. Only contains the filename (without extension) to upload.
     * @param {Function} config.existFn.callback The callback function to call after checking existence
     * @param {Boolean} config.existFn.callback.exists true if the file exists, false otherwise
     * @param {String} [config.existConfirmTitle] The title of confirm dialog if the file already exists
     * @param {String} [config.existConfirmDesc] The description of confirm dialog if the file already exists
     * @param {String} [config.title] The dialog box title
     * @param {String} [config.icon] The dialog box icon
     * @param {String} [config.helpMsg] The dialog box hint
     */
    open: function (config)
    {
        this._importFn = config.importFn;
        this._url = config.url;
        this._errorMsg = config.importErrorMsg || "{{i18n PLUGINS_WEB_ADMINISTRATOR_SKINS_HANDLE_IMPORT_ERROR}}";
        this._title = config.title || "{{i18n PLUGINS_WEB_ADMINISTRATOR_IMPORT_DIALOG_CAPTION}}";
        
        this._existFn = config.existFn;
        this._existConfirmTitle = config.existConfirmTitle || "{{i18n PLUGINS_WEB_ADMINISTRATOR_IMPORT_TEST_EXIST_ALERT}}";
        this._existConfirmDesc = config.existConfirmDesc || "{{i18n PLUGINS_WEB_ADMINISTRATOR_IMPORT_TEST_EXIST_ALERT_DESC}}";
        
        this._delayedInitialize(this._title, config.icon || Ametys.getPluginResourcesPrefix("web") + '/img/administrator/skins/import_16.png', config.helpMsg || "{{i18n PLUGINS_WEB_ADMINISTRATOR_IMPORT_DIALOG_HINT}}");

        this._box.show();
    },

    /**
	 * Initialize the dialog box
	 * @param {String} title The title of the dialog box.
	 * @param {String} icon The full path to icon (16x16 pixels) for the dialog box
	 * @param {String} helpmessage The message displayed at the top of the dialog box.
	 * @private
	 */
    _delayedInitialize: function (title, icon, helpmessage)
    {
    	if (!this._initialized)
		{
			this._box = Ext.create('Ametys.window.DialogBox', {
				title: title,
				icon: icon,
				
				width: 430,
				scrollable: true,
				layout: 'fit',
				
				items: [{
							xtype: 'form',
							border: false,
							defaults: {
								cls: 'ametys',
								labelAlign: 'top',
								labelSeparator: ''
							},
							items: [{
										xtype: 'component',
										cls: 'a-text',
										html: helpmessage
									}, 
									{
										xtype: 'filefield',
										name: 'importfile',
										id: 'importfile-file',
										fieldLabel: "{{i18n PLUGINS_WEB_ADMINISTRATOR_IMPORT_DIALOG_FILE}} *",
					                    allowBlank: false,
					                    emptyText: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILEUPLOAD_FIELD_EMPTYTEXT}}",
					                    buttonText: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILEUPLOAD_FIELD_BUTTONTEXT}}",
										width: 370,
										
										listeners: {'change': {fn: this._selectFile, scope: this}}
									}
							]
						}
				],
				
				defaultFocus: 'importfile',
				closeAction: 'hide',
				buttons: [{
					text :"{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILEUPLOAD_BOX_OK}}",
					disabled: true,
					handler : Ext.bind(this._validate, this)
				}, {
					text :"{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILEUPLOAD_BOX_CANCEL}}",
					handler: Ext.bind(function() {this._box.hide();}, this) 
				}]
			});
			
			this._initialized = true;
		}
		else
		{
			this._box.down('#importfile-file').reset();
			this._box.setIcon(icon);
			this._box.setTitle(title);
			this._box.down('form').items.get(0).update(helpmessage);
		}
    },

    /**
	 * Function called when the file input change
	 * @param {Ext.form.field.File} input The file input
	 * @param {String} name The file name
	 * @private
	 */
	_selectFile: function (input, name)
	{
		// _uploading boolean is used to prevent to execution of this code twice, because for some reasons, in IE, the
		// change event is raised again when the form is submitted (with an empty value)
		if (!this._uploading)
		{
			var disabled = !Ext.String.endsWith(name, '.zip', true);
			this._box.getDockedItems('toolbar[dock="bottom"]')[0].items.get(0).setDisabled(disabled);
			if (disabled)
			{
				Ametys.log.ErrorDialog.display({
					title:  "{{i18n plugin.web:PLUGINS_WEB_ADMINISTRATOR_IMPORT_SUBMIT_ZIP_ERROR}}",
					text: "{{i18n plugin.web:PLUGINS_WEB_ADMINISTRATOR_IMPORT_SUBMIT_ZIP_ERROR_DESC}}",
		    		details: "",
		    		category: this.self.getName()
				});
			}
		}
	},
	
    /**
     * Handler for the 'ok' button of the dialog box
     * @private
     */
    _validate: function ()
    {
        var form = this._box.down('form').getForm();
        if (!form.isValid())
        {
            return;
        }
        
        // Check existence first
        if (Ext.isFunction (this._existFn))
        {
        	var filename = form.findField("importfile").getValue();
        	filename = filename.substring(0, filename.length - 4);
        	
        	this._existFn ([filename], this._existCb);
        }
        else
        {
        	// Submit form
            this._submit();
        }
        
    },
    
    /**
     * @private
     * Submit the form
     */
    _submit: function ()
    {
    	this._uploading = true;
    	
    	this._box.down('form').getForm().submit({
            url: this._url,
            params: {
                contextualParameters: Ext.JSON.encode(Ametys.getAppParameters())
            },
            
            waitTitle: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILEUPLOAD_SUBMITFORM_TITLE}}",
			waitMsg: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILEUPLOAD_SUBMITFORM_MSG}}",

            success: Ext.bind(this._submitSuccess, this),
            failure: Ext.bind(this._submitFailure, this)
        });
    },
    
    /**
     * @private
     * Callback function invoked after testing existence
     * @param {Boolean} exists True if a file with same name already exists
     */
    _existCb: function (exists)
    {
    	if (!exists)
    	{
    		// Submit form
    		this._submit();
    	}
    	else
    	{
    		// Replace existing skin ?
    		Ametys.Msg.confirm (this._existConfirmTitle,
    				this._existConfirmDesc,
					this._confirmUpdate,
					this
    		);
    	}
    },
    
    /**
     * @private
     * Callback function invoked after #_existCb confirm dialog box
     * @param {String} answer The user answer
     */
    _confirmUpdate: function (answer)
    {
    	if (answer == 'yes')
    	{
    		this._submit();
    	}
    },

    /**
     * Callback for the "cancel" button of the dialog. Close the dialog.
     * @private
     */
    _cancel: function ()
    {
        this._box.hide();
    },

    /**
	 * The function to call when {@link #_submit} succeeded.
	 * @param {Ext.form.Basic} form The form that requested the submit action
	 * @param {Ext.form.action.Action} action The Action class.
	 */
	_submitSuccess: function (form, action)
    {
    	this._uploading = false;
    	
    	if (this._importFn)
		{
    		this._box.hide();
			Ext.Function.defer (this._importFn, 0, null, [action.result]);
		}
    },

    /**
	 * The function to call when {@link #_submit} failed.
	 * @param {Ext.form.Basic} form The form that requested the submit action
	 * @param {Ext.form.action.Action} action The Action class.
	 */
	_submitFailure: function (form, action)
    {
    	this._uploading = true;
    	
    	if (action.result.error == "rejected")
		{
			Ametys.log.ErrorDialog.display({
				title: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILEUPLOAD_ERROR_MSG}}", 
				text: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILEUPLOAD_ERROR_FILEREJECTED}}",
	    		details: "",
	    		category: this.self.getName()
			});
		}
		else
		{
			Ametys.log.ErrorDialog.display({
				title: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILEUPLOAD_ERROR_MSG}}", 
				text: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILEUPLOAD_ERROR_ON_SERVER}}",
	    		details: action.result.error ? action.result.error.message + "\n" + action.result.error.stacktrace : "",
	    		category: this.self.getName()
			});
		}
    }
});