/*
 *  Copyright 2017 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 edit a multilingual string.<br>
 * The form displays a text field for each configured languages.<br>
 * See #open method
 */
Ext.define('Ametys.helper.EditMultilingualString', {
	singleton: true,
	
	/**
	 * @property _cbFn {Function} The callback function to call after editing multilingual string
	 * @private
	 */
    
    /**
     * @property _allowBlank {Boolean} If 'false' check at least one value is not empty before validating
     * @private
     */
	
	/**
	 * @property _box {Ametys.window.DialogBox} The dialog box
	 * @private
	 */
    
    /**
     * @property _blankErrorActive {Boolean} True when the allowBlank validation fails
     * @private
     */

	/**
	 * Open dialog to edit each language's values of a multilingual string
     * @param {Object} config The configuraiton options:
     * @param {Object[]} config.languages (required) Array of the available languages. Excepted properties for each language are:
     * @param {Object[]} config.languages.name The language code such as 'fr', 'en'
     * @param {Object[]} config.languages.label The language label
	 * @param {String} config.title (required) The title of the dialog box.
     * @param {String} [config.iconCls="ametysicon-edit45"] One or more space separated CSS classes to be applied to the dialog icon
	 * @param {String} [config.icon] The full path to icon (16x16 pixels) for the dialog box
	 * @param {Object} [config.values] The values to display at startup
     * @param {Boolean} [config.allowBlank=true] Set to 'false' to validate that at least one value is not empty
     * @param {Object} [config.itemConfig] An additional configuration object to apply to all textfield items. Use it to add validation for all textfield for example.
	 * @param {Function} config.callback The method that will be called when the dialog box is closed. The method signature is <ul><li>id: The id of the file</li><li>filename: The name of the file</li><li>size: The size in byte of the file</li><li>viewHref: The href to VIEW the file</li><li>downloadHref: The href to DOWNLOAD the file</li></ul> The method can return false to made the dialog box keep open (you should display an error message in this case)
     * * @param {Boolean} [config.readOnly=false] To make fields readonly
     * @param {Object} config.callback.values The edited values for each languages
     */
	open: function(config)
	{
		this._cbFn = config.callback;
		this._allowBlank  = !(config.allowBlank === false);
		this._blankErrorActive = false;
        
        var languages = config.languages || [];
        if (languages.length == 0)
        {
            // No available languages
            Ametys.Msg.alert("{{i18n PLUGINS_CORE_UI_HELPER_EDIT_MULTILINGUAL_NO_LANGUAGE_ERROR}}");
            return;    
        }
        
		this._initialize(config);  
        
		this._box.show();
        
        // set focus on first text field
        this._getForm().getFields().get(0).focus();
	},
	
	/**
	 * Initialize the dialog box
     * @param {Object} config The configuraiton options:
     * @param {Object[]} config.languages (required) Array of the available languages. Excepted properties for each language are:
     * @param {Object[]} config.languages.name The language code such as 'fr', 'en'
     * @param {Object[]} config.languages.label The language label
     * @param {String} config.title (required) The title of the dialog box.
     * @param {String} [config.iconCls="ametysicon-edit45"] One or more space separated CSS classes to be applied to the dialog icon
     * @param {String} [config.icon] The full path to icon (16x16 pixels) for the dialog box
     * @param {Object} [config.values] The values to display at startup
	 * @param {String} config.regex A RegExp string to be tested against the field value during validation. Can be null.
	 * @param {String} config.regexText The error text to display if regex is used and the test fails during validation. Can be null to use default error text.
	 * @private
	 */
	_initialize:  function(config)
	{
        var values = config.values || {};
        var languages = config.languages;
        
        var items = [];
        
        var me = this;
        Ext.Array.each(languages, function(language) {
            items.push(Ext.apply({
                fieldLabel: language.label,
                name: language.name,
                value: values[language.name] || '',
                readOnly: config.readOnly,
                listeners: {
			        change: Ext.bind(me._onChange, me)
			    }
            }, config.itemConfig || {}));
        });

		this._box = Ext.create('Ametys.window.DialogBox', {
			title: config.title,
			icon: config.icon,
            iconCls: config.icon ? null : config.iconCls || 'ametysicon-edit45',
			
			width: 500,
            maxHeight: 400,
			scrollable: true,
			layout: 'form',
            
			items: [{
						xtype: 'form',
                        defaults : {
			                cls: 'ametys',
			                labelWidth: 80,
                            labelSeparator: '',
			                msgTarget: 'side',
			                anchor:'90%',
			                xtype: 'textfield'
			            },
						border: false,
						items: items
					}
			],

			
			closeAction: 'destroy',
			
			referenceHolder: true,
			defaultButton: 'validate',
			
			buttons : [{
				reference: 'validate',
				text :"{{i18n PLUGINS_CORE_UI_HELPER_EDIT_MULTILINGUAL_OK}}",
				handler : Ext.bind(this._ok, this)
			}, {
				text :"{{i18n PLUGINS_CORE_UI_HELPER_EDIT_MULTILINGUAL_CANCEL}}",
				handler: Ext.bind(function() {this._box.close();}, this) 
			}],
            
            listeners: {
                close: Ext.bind(this._onClose, this)
            }
		});
	},
    
    /**
     * @private
     * Listener when the value of a field is changed
     * @param {Ext.form.field.Field} fd The field
     * @param {Object} newValue The new value
     * @param {Object} oldValue The original value
     */
    _onChange: function (fd, newValue, oldValue)
    {
        if (this._blankErrorActive && newValue)
        {
            fd.clearInvalid();
            
            this._getForm().getFields().each(function(fd) {
                if (Ext.isEmpty(fd.getValue()))
                {
	                fd.clearInvalid();
                }
            });
            
            this._blankErrorActive = false;
        }
    },
	
    /**
     * Returns the current form
     * @return {Ext.form.Basic} The form
     */
    _getForm: function()
    {
        return this._box.down('form').getForm();  
    },
    
	/**
     * @private
	 * Validate the dialog box's form
	 */
	_ok: function()
	{
		var form = this._getForm();
		if (!form.isValid())
		{
			return;
		}

        var values = {};
        form.getFields().each(function(fd) {
            var value = fd.getValue();
            if (!Ext.isEmpty(value))
            {
                values[fd.getName()] = value;
            }
        });
		
        if (!this._allowBlank && Ext.Object.isEmpty(values))
        {
            this._blankErrorActive = true;
            
            form.getFields().each(function(fd) {
	            fd.markInvalid("{{i18n PLUGINS_CORE_UI_HELPER_EDIT_MULTILINGUAL_MANDATORY_ERROR}}");
	        });
            return;
        }
        
		if (this._cbFn)
		{
			Ext.Function.defer (this._cbFn, 0, null, [values]);
		}
		
        this._validated = true;
		this._box.close();
	},
	
    /**
     * @private
     * Listener when closing the dialog box
     * @param {Boolean} validate true the dialog box was closing after cliking on 'Ok' button
     */
    _onClose: function(validate)
    {
        if (!this._validated && this._cbFn)
        {
            Ext.Function.defer (this._cbFn, 0, null, [null]);
        }
    }
	
});