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

/**
 * This helper provides a dialog box to choose a resource from local hard drive and upload it
 * See #open method.
 */
Ext.define('Ametys.plugins.skineditor.resources.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: {
			'locked': "{{i18n plugin.explorer:PLUGINS_EXPLORER_FILE_HANDLE_ADD_LOCKED}}",
            'infected': "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_INFECTED}}",
			'rejected': "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_REJECTED}}",
			'already-exist': "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_ALREADY_EXISTS}}",
			'unzip-error': "{{i18n plugin.explorer:PLUGINS_EXPLORER_FILE_HANDLE_ADD_UNZIP_ERROR}}" 
	},
	
	/**
     * Allow the user to upload a file from local hard drive
     * @param {String} skinName The skin name
     * @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 (skinName, parentPath, callback)
	{
		this._cbFn = callback;
		
		this._delayedInitialize ();
		this._box.show();
		
		this._initForm (skinName, 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: '100%',
                msgTarget: 'title'
			},
			fieldDefaults : {
				labelAlign: 'right',
				labelSeparator: '',
				labelWidth: 50
			},
			
			items : [{
				xtype: 'fileuploadfield',
				itemId: 'form-file',
				name: 'filename',
				emptyText: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_EMPTY_TEXT}}",
				fieldLabel: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_FILE}}",
				buttonText: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_BROWSE}}",
				allowBlank: false,
				width: 300,
				listeners: {
					change: {fn: this._onFileChange, scope: this}
				}
			}, {
				xtype: 'checkboxfield',
				itemId: 'form-unzip-display',
				name: 'unzip-display',
				boxLabel: "{{i18n plugin.explorer:PLUGINS_EXPLORER_FILE_HANDLE_ADD_UNZIP}}",
				hideLabel: true,
				anchor: '100%',
				checked: false,
				hidden: true,
				listeners: {
					change: {fn: this._onCheck, scope: this}
				}
			}, {
				xtype: 'component',
				itemId: 'update-file-hint',
				html: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_UPDATE_HINT}}",
				hidden: true
			}, {
				xtype: 'hiddenfield',
				name: 'parentPath'
			}, {
                xtype: 'hiddenfield',
                name: 'skinName'
            }, {
				xtype: 'hiddenfield',
				name: 'id'
			}, {
				xtype: 'hiddenfield',
				name: 'unzip'
			}]
		});
		
		this._form = formPanel.getForm();
		
		this._box = Ext.create('Ametys.window.DialogBox', {
			title :"{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD}}",
			iconCls : 'ametysicon-upload119',
			
			layout :'fit',
			width : 430,
			
			items: formPanel,
			
			defaultFocus: 'form-file',
			closeAction: 'hide',
			
			buttons: [{
				itemId: 'upload-file-btn-ok',
				text :"{{i18n plugin.core-ui:PLUGINS_CORE_UI_DIALOG_OK}}",
				handler : Ext.bind(this._add, this)
			},{
				itemId: 'upload-file-btn-update',
				text :"{{i18n plugin.core-ui:PLUGINS_CORE_UI_DIALOG_REPLACE}}",
				hidden: true,
				handler : Ext.bind(this._update, this)
			},{
				itemId: 'upload-file-btn-add-rename',
				text :"{{i18n plugin.core-ui:PLUGINS_CORE_UI_DIALOG_ADDANDRENAME}}",
				hidden: true,
				handler : Ext.bind(this._addAndRename, this)
			},{
				text :"{{i18n plugin.core-ui:PLUGINS_CORE_UI_DIALOG_CANCEL}}",
				handler : Ext.bind(function() {this._box.hide();}, this)
			}]
		});
		
		this._initialized = true;
		return true;
	},
	
	/**
	 * @private
	 * Initialize or reinitialize the form with the appropriate values.
	 * @param {String} skinName The name of the skin concerned
	 * @param {String} parentPath The parent path
	 */
	_initForm: function(skinName, parentPath)
	{
		this._form.findField('parentPath').setValue(parentPath);
        this._form.findField('skinName').setValue(skinName);
		this._form.findField('id').setValue(id);
		this._form.findField('filename').reset();
		this._form.findField('unzip-display').hide();
		this._form.findField('unzip-display').reset();
		this._form.findField('unzip').setValue('false');
		this._form.owner.queryById('update-file-hint').hide();
		
		// Show/Hide btns
		this._box.queryById('upload-file-btn-ok').show();
		this._box.queryById('upload-file-btn-update').hide();
		this._box.queryById('upload-file-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 {String} oldValue the previous value of the field
	 * @param {Object} eOpts The event option object
	 */
	_onFileChange: function(field, value, oldValue, eOpts)
	{
		if (value)
		{
            // Value is like 'C:\fakepath\FILENAME.EXT'
            var filename = value;
            if (filename.lastIndexOf("/") > 0)
	        {
	            filename = filename.substring(filename.lastIndexOf("/") + 1);
	        }
	        else if (filename.lastIndexOf("\\") > 0)
	        {
	            filename = filename.substring(filename.lastIndexOf("\\") + 1);
	        }
        
			Ametys.data.ServerComm.callMethod({
				role: 'org.ametys.plugins.skineditor.resources.SkinResourceDAO', 
				methodName: 'checkSourceExists',
				parameters: [this._form.findField('skinName').getValue(), this._form.findField('parentPath').getValue(), filename],
				callback: {
					handler: this._checkNameCb,
					scope: this,
					arguments: {
						filename: value
					}
				},
				errorMessage: "{{i18n plugin.explorer:PLUGINS_EXPLORER_FILE_HANDLE_CHECK_NAME_ERROR}}"
			});
		}
		else
		{
			this._refreshDialog(value);
		}
	},
	
	/**
	 * @private
	 * Callback function invoked after checking file name
	 * @param {Boolean} exists true if the resource with same name already exists
	 * @param {Object} args the callback arguments
	 * @param {String} args.filename the name of the file
	 */
	_checkNameCb: function (exists, args)
	{
		if (exists)
		{
			this._form.findField('unzip-display').hide();
			this._form.owner.queryById('update-file-hint').show();
			
			this._box.queryById('upload-file-btn-ok').hide();
			this._box.queryById('upload-file-btn-update').show();
			this._box.queryById('upload-file-btn-add-rename').show();
		}
		else
		{
			this._refreshDialog(args.filename);
		}
	},
	
	/**
	 * @private
	 * Refreshes the dialog's buttons depending on the upload candidate
	 * @param {String} filename the name of the file
	 */
	_refreshDialog: function(filename)
	{
		this._form.owner.queryById('update-file-hint').hide();
		
		var unzip = this._form.findField('unzip-display');
		if (Ext.String.endsWith(filename, '.zip'))
		{
			unzip.show();
		}
		else
		{
			unzip.hide();
		}
		
		this._box.queryById('upload-file-btn-ok').show();
		this._box.queryById('upload-file-btn-update').hide();
		this._box.queryById('upload-file-btn-add-rename').hide();
	},
	
	/**
	 * @private
	 * Listener when the 'unzip' checkbox is check or uncheck
	 * Updates the hidden field 'unzip' accordingly.
	 * @param {Ext.form.field.Field} field The field changed
	 * @param {Object} newValue The new value
	 * @param {Object} oldValue The original value
	 * @param {Object} eOpts The event option object
	 */
	_onCheck: function(field, newValue, oldValue, eOpts)
	{
		this._form.findField('unzip').setValue(newValue.toString());
	},
	
	/**
	 * @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()
	{
		var extraParams = {};
		var appParams = Ametys.getAppParameters();
		
		for (var i in appParams)
		{
			extraParams[i] = appParams[i];
		}
		
		if (this._form.isValid())
		{
			this._form.submit({
				url : Ametys.getPluginDirectPrefix('skineditor') + '/action/file/add',
				params : extraParams,
				
				waitMsg: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_WAIT_MSG}}",
				waitTitle: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_WAIT_TITLE}}",
				
				success: this._success,
				failure: this._failure,
				scope: this
			});
		}
	},
	
	/**
	 * @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()
	{
		var extraParams = {};
		var appParams = Ametys.getAppParameters();
		
		for (var i in appParams)
		{
			extraParams[i] = appParams[i];
		}
		
		if (this._form.isValid())
		{
			this._form.submit({
				url : Ametys.getPluginDirectPrefix('skineditor') + "/action/file/update",
				params : extraParams,
				
				waitMsg: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_WAIT_MSG}}",
				waitTitle: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_WAIT_TITLE}}",
				
				success: this._success,
				failure: this._failure,
				scope: this
			});
		}
	},
	
	/**
	 * @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()
	{
		var extraParams = {};
		var appParams = Ametys.getAppParameters();
		
		for (var i in appParams)
		{
			extraParams[i] = appParams[i];
		}
		
		if (this._form.isValid())
		{
			this._form.submit({
				url : Ametys.getPluginDirectPrefix('skineditor') + "/action/file/add-rename",
				params : extraParams,
				
				waitMsg: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_WAIT_MSG}}",
				waitTitle: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_WAIT_TITLE}}",
				
				success: this._success,
				failure: this._failure,
				scope: this
			});
		}
	},
	
	/**
	 * @private
	 * This function is called when the submit of the form succeed
	 * @param {Ext.form.Basic} form The form that requested the action
	 * @param {Ext.form.action.Action} action The Action class. 
	 */
	_success: function(form, action)
	{
		if (this._cbFn)
		{
			Ext.Function.defer (this._cbFn, 0, null, [action.result.name, action.result.path, action.result.parentPath]);
		}
		
		this._box.hide();
	},

	/**
	 * @private
	 * This function is called when the submit of the form failed
	 * @param {Ext.form.Basic} form The form that requested the action
	 * @param {Ext.form.action.Action} action The Action class. 
	 */
	_failure: function(form, action)
	{
		var msg = action.result.message || '';
		if (msg in this._errorMsg)
		{
			msg = this._errorMsg[msg];
		}
		
		Ametys.log.ErrorDialog.display({
			title: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD}}",
			text: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_FILE_HANDLE_ADD_ERROR}}<br/>" + msg
		});
	}
});