/*
 *  Copyright 2019 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 UI helper provides a dialog box to upload a file from hard drive
 * See #open method.
 * @private
 */
Ext.define('Ametys.plugins.coreui.parameter.files.UploadFile', {
	singleton: true,
	
	/**
	 * @property {Boolean} _initialized True if the dialog box has been initialized.
	 * @private
	 */
	/**
	 * @property {Ext.form.Basic} _form The inner basic form.
	 * @private
	 */
	/**
	 * @property {Ametys.window.DialogBox} _box The dialog box
	 * @private
	 */
	
	/**
	 * @property {Object} The error messages
	 * @private
	 */
	_errorMsg: {
        'infected': "{{i18n PLUGINS_CORE_UI_FILE_HANDLE_INFECTED}}",
		'rejected': "{{i18n PLUGINS_CORE_UI_FILE_HANDLE_REJECTED}}",
		'already-exist': "{{i18n PLUGINS_CORE_UI_FILE_HANDLE_ADD_ALREADY_EXISTS}}"
	},
	
	/**
	 * Allow the user to upload a file from local hard drive
	 * @param {String} parentPath The path of parent folder
	 * @param {Function} callback The callback function called when the file was uploaded. Has the following parameters
	 * @param {String} callback.path The path of uploaded file
	 * @param {String} callback.parentPath The path of parent folder
	 * @param {Boolean} callback.reload True if a reload is needed
	 */
	open: function(parentPath, callback)
	{
		this._cbFn = callback;
		
		this._delayedInitialize();
		this._box.show();
		
		this._initForm(parentPath);
	},
	
	/**
	 * @private
	 * Initialize the dialog box
	 * @return {Boolean} true if the box has been initialized (or if it was already initialized).
	 */
	_delayedInitialize: function()
	{
		if (this._initialized)
		{
			return true;
		}
		
		var formPanel = Ext.create('Ext.form.Panel', {
			border: false, 
			scrollable: true,
			defaults: {
				cls: 'ametys',
				anchor: '95%'
			},
			fieldDefaults : {
				labelAlign: 'right',
				labelSeparator: '',
				labelWidth: 50
			},
			
			items : [{
				xtype: 'fileuploadfield',
				name: 'filename',
				emptyText: "{{i18n PLUGINS_CORE_UI_FILE_HANDLE_ADD_EMPTY_TEXT}}",
				fieldLabel: "{{i18n PLUGINS_CORE_UI_FILE_HANDLE_ADD_FILE}}",
				buttonText: "{{i18n PLUGINS_CORE_UI_FILE_HANDLE_ADD_BROWSE}}",
				allowBlank: false,
				width: 300,
				listeners: {
					change: {fn: this._onFileChange, scope: this}
				}
			}, {
				xtype: 'component',
				id: 'update-file-param-hint',
				html: "{{i18n PLUGINS_CORE_UI_FILE_HANDLE_UPDATE_HINT}}",
				hidden: true
			}, {
				xtype: 'hiddenfield',
				name: 'parentPath'
			}]
		});
		
		this._form = formPanel.getForm();
		
		this._box = Ext.create('Ametys.window.DialogBox', {
			title :"{{i18n PLUGINS_CORE_UI_FILE_HANDLE_ADD}}",
            iconCls: 'ametysicon-arrow-up-from',
			
			layout :'fit',
			width : 430,
			items: formPanel,
			
			defaultFocus: formPanel.getForm().findField('filename'),
			closeAction: 'hide',
			
			buttons: [{
				id: 'upload-file-param-btn-ok',
				text :"{{i18n PLUGINS_CORE_UI_DIALOG_OK}}",
				handler : Ext.bind(this._add, this)
			},{
				id: 'upload-file-param-btn-update',
				text :"{{i18n PLUGINS_CORE_UI_DIALOG_REPLACE}}",
				hidden: true,
				handler : Ext.bind(this._update, this)
			},{
				id: 'upload-file-param-btn-add-rename',
				text :"{{i18n PLUGINS_CORE_UI_DIALOG_ADDANDRENAME}}",
				hidden: true,
				handler : Ext.bind(this._addAndRename, this)
			},{
				text :"{{i18n PLUGINS_CORE_UI_DIALOG_CANCEL}}",
				handler : Ext.bind(function() {this._box.hide();}, this)
			}],
			
            listeners: {
                'show': function() {
                    var me = this ;
                    window.setTimeout(function() { 
                        me._form.findField('filename').fileInputEl.dom.click(); 
                    }, 1); // Timeout required so listeners are correctly attached
                },
                scope: this
            }
		});
		
		this._initialized = true;
		return true;
	},
	
	/**
	 * @private
	 * Initialize or reinitialize the form with the appropriate values.
	 * @param {String} parentPath The folder parent path
	 */
	_initForm: function(parentPath)
	{
		this._form.findField('parentPath').setValue(parentPath);
		this._form.findField('filename').reset();
		this._form.owner.queryById('update-file-param-hint').hide();
		
		// Show/Hide btns
		this._box.queryById('upload-file-param-btn-ok').show();
		this._box.queryById('upload-file-param-btn-update').hide();
		this._box.queryById('upload-file-param-btn-add-rename').hide();
	},
	

	/**
	 * @private
	 * Listener when file upload field changed.
	 * Checks if a resource with this name already exists in the given folder, and then, appropriately update the form and buttons.
	 * @param {Ext.ux.form.FileUploadField} field the file field
	 * @param {String} value The file value returned by the underlying file input field
	 * @param {Object} eOpts The event option object
	 */
	_onFileChange: function(field, value, eOpts)
	{
		var me = this;
		var path = this._form.findField('parentPath').getValue();
		
		Ametys.data.ServerComm.callMethod({
			role: 'org.ametys.core.ui.RibbonControlsManager',
			id: 'org.ametys.plugins.core.ui.parameter.files.File.add',
			methodName: 'fileExists',
			parameters: [path, value],
			callback: {
				scope: this,
				handler: function(result, args)
				{
					if (result)
					{
						me._form.owner.queryById('update-file-param-hint').show();
						
						me._box.queryById('upload-file-param-btn-ok').hide();
						me._box.queryById('upload-file-param-btn-update').show();
						me._box.queryById('upload-file-param-btn-add-rename').show();
					}
					else
					{
						me._form.owner.queryById('update-file-param-hint').hide();
						
						me._box.queryById('upload-file-param-btn-ok').show();
						me._box.queryById('upload-file-param-btn-update').hide();
						me._box.queryById('upload-file-param-btn-add-rename').hide();
					}
				}
			},
			errorMessage: {
				msg: "{{i18n PLUGINS_CORE_UI_PARAMETERS_FILE_EXIST_ERROR}}",
				category: Ext.getClassName(this) + '._onFileChange'
			},
			waitMessage: true
		});
	},
	
	/**
	 * @private
	 * This function is called when the 'Ok' button of the dialog box #_box is pressed
	 * Submits the form to the server in order to add the file.
	 */
	_add: function()
	{
        this._addUpateOrRename("add");
	},
	
	/**
	 * @private
	 * This function is called when the 'Replace' button of the dialog box #_box is pressed
	 * Submits the form to the server in order to update the file.
	 */
	_update: function()
	{
        this._addUpateOrRename("update");
	},
	
	/**
	 * @private
	 * This function is called when the 'Rename' button of the dialog box #_box is pressed
	 * Submits the form to the server in order to add then rename the file.
	 */
	_addAndRename: function()
	{
        this._addUpateOrRename("add-rename");
	},
	
	/**
     * @private
     * This function is called when the one of the import button of the dialog box #_box is pressed
     * Submits the form to the server in order to import the file.
     */
    _addUpateOrRename: function(mode)
    {
        if (this._form.isValid())
        {
            var parameters = [];
            parameters.push(this._form.getFieldValues()["parentPath"]);
            parameters.push(mode || "add");
            
            parameters.push(this._form.findField('filename').getFiles()[0]);

            Ametys.data.ServerComm.callMethod({
                role: 'org.ametys.plugins.core.ui.parameter.files.AddOrUpdateFile', 
                methodName: 'addOrUpdateFile',
                parameters: parameters,
                priority: Ametys.data.ServerComm.PRIORITY_LONG_REQUEST,
                callback: {
                    handler: this._addUpateOrRenameCb,
                    scope: this,
                },
                errorMessage: "{{i18n PLUGINS_CORE_UI_FILE_HANDLE_ADD_RENAME_UPDATE_ERROR}}",
                
                progressMessage: {
                    title: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_WAIT_TITLE}}",
                    msg: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_WAIT_MSG}}"
                }
            });
        }
    },
    
    /**
     * @private
     * This function is called after the resources have tried to be imported
     * @param {Object} result The results
     */
    _addUpateOrRenameCb: function(result)
    {
        if (result.success)
        {
            this._success(result);
        }
        else
        {
            this._failure(result);
        }
    },
	
	/**
	 * @private
	 * This function is called when the submit of the form succeed
     * @param {Object} result The results
	 */
	_success: function(result)
	{
		if (this._cbFn)
		{
			Ext.Function.defer(this._cbFn, 0, null, [result.name, result.path, result.parentPath]);
		}
		
		this._box.hide();
	},

	/**
	 * @private
	 * This function is called when the submit of the form failed
     * @param {Object} result The results
	 */
	_failure: function(result)
	{
		var msg = result.msg || '';
		if (msg in this._errorMsg)
		{
			msg = this._errorMsg[msg];
		}
		
		Ametys.log.ErrorDialog.display({
			title: "{{i18n PLUGINS_CORE_UI_FILE_HANDLE_ADD}}",
			text: "{{i18n PLUGINS_CORE_UI_FILE_HANDLE_ADD_ERROR}}" + msg
		});
	}
});