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

/**
 * Field that displays allows to type in a password. If no password is set the field is empty, else
 * the field is initially disabled.
 */
Ext.define('Ametys.form.field.Password', {
    extend: 'Ametys.form.AbstractFieldsWrapper',
    alias: ['widget.passwordfield', 'widget.password'],
    alternateClassName: ['Ext.form.PasswordField', 'Ext.form.Password', 'Ext.form.field.Password'],
    
    statics: {
    	
    	/**
         * @protected
         * @readonly
         * @property {Number} 
         * the mode when no password has been defined yet
         */
        MODE_NOPASSWORD: 0,
        /**
         * @protected
         * @readonly
         * @property {Number} 
         * the mode when setting a password 
         */
        MODE_CHANGEPASSWORD: 1,
        /**
         * @protected
         * @readonly
         * @property {Number} 
         * the mode when displaying a password
         */
        MODE_SEEPASSWORD: 2,
        /**
         * @protected
         * @readonly
         * @property {String} 
         * the tooltip of the button for changing the password
         */
        RESET_PASSWORD_TEXT: "{{i18n PLUGINS_CORE_UI_PASSWORD_RESET}}",
        /**
         * @protected
         * @readonly
         * @property {String} 
         * the tooltip of the button for resetting the password
         */
        CHANGE_PASSWORD_TEXT: "{{i18n PLUGINS_CORE_UI_PASSWORD_CHANGE}}"
    },
    
    /**
     * @cfg {Object} passwordConfig The configuration object for the first text field. Note that many configuration can be set directly here and will we broadcasted to underlying field (allowBlank...)
     */
    /**
     * @cfg {Object} buttonConfig The configuration object for the button to change password.
     */
    /**
     * @cfg {Boolean} allowBlank
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-allowBlank}.
     */
    /**
     * @cfg {Boolean} blankText
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-blankText}.
     */
    /**
     * @cfg {String} emptyText
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-emptyText}.
     */
    /**
     * @cfg {String} invalidText
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-invalidText}.
     */
    /**
     * @cfg {RegExp} maskRe
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-maskRe}.
     */
    /**
     * @cfg {Number} maxLength
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-maxLength}.
     */
    /**
     * @cfg {String} maxLengthText
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-maxLengthText}.
     */
    /**
     * @cfg {Number} minLength
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-minLength}.
     */
    /**
     * @cfg {String} minLengthText
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-minLengthText}.
     */
    /**
     * @cfg {RegExp} regex
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-regex}.
     */
    /**
     * @cfg {String} regexText
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-regexText}.
     */
    /**
     * @cfg {Boolean} selectOnFocus
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-selectOnFocus}.
     */
    /**
     * @cfg {Number} size
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-size}.
     */
    /**
     * @cfg {RegExp} stripCharsRe
     * This property is copied to underlying text fields. See {@link Ext.form.field.Text#cfg-stripCharsRe}.
     */

	/**
	 * @private
	 * @property {Number} _mode The current mode of the widget. One of MODE_CHANGEPASSWORD, MODE_SEEPASSWORD and MODE_CHANGEPASSWORD.
	 */
    /**
     * @private
     * @property  {String} _previousValue the memorized value of the field
     */
    /**
     * @private
	 * @property {Ext.form.field.Text} _field the field containing the password
	 */
    /**
     * @private
	 * @property {Ext.button.Button} _button the button allowing to change/save the password's value
	 */
    /**
     * @private
     * @property  {Boolean} _initiallyInSeeMode true if the saved password is the good one, false otherwise
     */
    
    initComponent: function() 
    {
        // password
        this._initPasswordField();
        
    	this._mode = Ametys.form.field.Password.MODE_NOPASSWORD;
    	
    	// Change password button 
    	var buttonConfig = this.buttonConfig || {};
    	
    	Ext.applyIf(buttonConfig, {
    		tooltip: '',
            cls: 'a-btn-lighter',
    		handler: Ext.bind(this._setToMode, this, [null], false),
    		margin: '1 0 0 0',
    		border: false
    	});
    	this._button = Ext.create('Ext.button.Button', buttonConfig);
    	
    	this.items = this._getItems();
    	
    	this.msgTarget = 'side';
    	
    	this.on('afterrender', this._adaptRenderToMode, this);
    	
        this.callParent(arguments);
    },
    
    /**
     * @protected
     * Initialize the password field. This function in called from {@link #initComponent} 
     */
    _initPasswordField: function()
    {
        // Password field
        var passwordConfig = this.passwordConfig || {};
            passwordConfig.inputType = 'password';
            passwordConfig.flex = 1;

        var propertiesToCopy = this._getConfigPropertiesToCopy();
        this._copyPropIfDefined(passwordConfig, propertiesToCopy, this.initialConfig);
        
        this._field = Ext.create('Ext.form.field.Text', passwordConfig);
    },
       
    /**
     * @protected
     * Retrieves the name of the configuration properties to copy to the underlying field 
     * @return {String[]} The name of the properties
     */
    _getConfigPropertiesToCopy: function()
    {
        return ['emptyText', 'invalidText', 'maskRe', 'maxLength', 'maxLengthText', 'minLength', 'minLengthText', 'regex', 'regexText', 'selectOnFocus', 'size', 'stripCharsRe'];
    },
    
    /**
     * @protected
     * Returns the items of the component. This function in called from {@link #initComponent}
     */
    _getItems: function()
    {
        return [this._field, this._button];
    },
    
    getErrors: function (value) 
    {
        if (this._mode == Ametys.form.field.Password.MODE_SEEPASSWORD)
        {
            return [];
        }
        else
        {
            return Ext.Array.merge(this.callParent(arguments), this._field.getErrors(value));
        }
    },
    
    getValue: function()
    {
        if (this._mode == Ametys.form.field.Password.MODE_SEEPASSWORD)
    	{
    		return null;
    	}
    	else 
    	{
    		return this._field.getValue();
    	}
    },
    
    getSubmitData: function ()
    {
    	return this._mode == Ametys.form.field.Password.MODE_SEEPASSWORD ? null : this.callParent(arguments);
    },
    
    setValue: function(value)
    {
		this._setToMode((value == undefined || value == '') ? Ametys.form.field.Password.MODE_NOPASSWORD : Ametys.form.field.Password.MODE_SEEPASSWORD);
    		
		this._field.setValue(value);
		this._onFieldSetValue(value);
    	
    	this.callParent(arguments);
    },
    
    enable: function()
    {
    	this._adaptRenderToMode();

    	this.callParent(arguments);
    },
    
    disable: function()
    {
    	this._adaptRenderToMode();

    	this.callParent(arguments);
    },
    
    /**
     * @private
     * Change the mode
     * @param {Number} mode The mode to set (see {@link #property-_mode}). The render is modified.
     */
    _setToMode: function(mode) 
    {
    	if (mode == null && this._initiallyInSeeMode && this._mode == Ametys.form.field.Password.MODE_CHANGEPASSWORD)
		{
    		// we should not be able to go in MODE_SEEPASSWORD if the field was not initially in that mode
    		mode = Ametys.form.field.Password.MODE_SEEPASSWORD;
		}
    	
    	if (this._mode == Ametys.form.field.Password.MODE_SEEPASSWORD)
    	{
    		if (mode == null)
			{
    			mode = Ametys.form.field.Password.MODE_CHANGEPASSWORD;
			}
    		
        	this._previousValue = this._field.getValue();
        	this._initiallyInSeeMode = true;
    	}
    	
    	this._mode = mode;

    	if (mode == Ametys.form.field.Password.MODE_SEEPASSWORD)
    	{
    		this._field.setValue(this._previousValue);
    		this._onFieldSetValue(this._previousValue);
    	}
        else if (mode == Ametys.form.field.Password.MODE_CHANGEPASSWORD)
        {
            this._field.setValue('');
            this._onFieldSetValue('');
        }

    	this._adaptRenderToMode();
    	this.clearInvalid();
    },
    
    /**
     * @private
     * Modify the render to adapt it to the current mode and current enable state
     */
    _adaptRenderToMode: function() 
    {
    	if (!this.rendered)
    	{
    		return;
    	}

    	if (this._mode == Ametys.form.field.Password.MODE_NOPASSWORD)
		{
    		this._field.setDisabled(this.disabled);
    		this._onFieldSetDisabled(this.disabled);
    		
    		this._button.hide();
		}
    	else
		{
    		if (this._mode == Ametys.form.field.Password.MODE_SEEPASSWORD)
			{
				this._field.disable();
				this._onFieldSetDisabled(true);
				
				this._button.setTooltip(Ametys.form.field.Password.CHANGE_PASSWORD_TEXT);
				this._button.setIconCls("a-field-password-change");
			}
    		else
			{
    			// The user is modifying the value
    			this._field.enable();
    			this._onFieldSetDisabled(false);
    			
                this._field.focus();
                
				this._button.setTooltip(Ametys.form.field.Password.RESET_PASSWORD_TEXT);
				this._button.setIconCls("a-field-password-reset");
			}

    		this._button.show();
		}
    },
    
    /**
     * @protected
     * Internal hook on field set value to add specific process in inherited classes
     * @param {String} value The value set
     */
    _onFieldSetValue: function(value)
    {
        // nothing
    },
    
    /**
     * @protected
     * Internal hook on field set disabled to add specific process in inherited classes
     * @param {Boolean} disabled True is disabled
     */
    _onFieldSetDisabled: function(disabled)
    {
        // nothing
    }
});