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

/**
 * Singleton class helper for extraction nodes edition.
 * @private
 */
 Ext.define('Ametys.plugins.extraction.edition.EditExtractionNodeDialog', {
    
    /**
     * @protected
     * @property {Object} _data The data of the node to edit
     */
    /**
     * @protected
     * @property {String} _mode The current edition mode ('new' or 'edit')
     */
    /**
     * @protected
     * @property {Ext.form.Panel} _form The form panel
     */
    /**
     * @private
     * @property {Ametys.window.DialogBox} _box The dialog box
     */
    /**
     * @private
     * @property {Function} _callback the callback function
     */
    /**
     * @private
     * @property {Boolean} _hasModifiedFields <code>true</code> if some fields have changed, <code>false</code> otherwise
     */
    /**
     * @private
     * @property {String} _separator The separator for the {@link Ametys.form.ConfigurableFormPanel} of the dialog box
     */
    _separator: '/',
    
    /**
     * Open dialog box to create a new extraction node
     * @param {Function} callback a callback function to invoke after the form is validated, can be null
     */
    add: function (callback)
    {
        this._mode = 'new';
        this._init(callback);
    },
    
    /**
     * Open dialog box to edit an extraction node
     * @param {Object} data data of the selected node
     * @param {Function} callback a callback function to invoke after the form is validated, can be null
     */
    edit: function (data, callback)
    {
        this._mode = 'edit';
        this._data = data;
        this._init(callback);
    },
    
    /**
     * @protected
     * Initializes th dialog box
     * @param {Function} callback a callback function to invoke after the form is validated, can be null
     */
    _init: function (callback)
    {
        this._callback = callback;
        this._openDialog ();
    },
    
    /**
     * @private
     * Show dialog box for extraction node edition
     */
    _openDialog: function ()
    {
        this._hasModifiedFields = false;
        
        this._form = Ext.create('Ametys.form.ConfigurableFormPanel', {
            defaultPathSeparator: this._separator,
            hideDisabledFields: true,
            flex: 1,
            listeners: {
                fieldchange: this._onFieldChanged,
                scope: this
            }
        });
        
        var dialogTitle = this._getDialogTitle();
        var dialogIconCls = this._getDialogIconCls();
        
        var okButton = {
            reference: 'okButton',
            text: "{{i18n PLUGINS_EXTRACTION_DIALOG_OK_BUTTON}}",
            handler: Ext.bind(this._onOk, this)
        };
        
        var cancelButton = {
            text: "{{i18n PLUGINS_EXTRACTION_DIALOG_CANCEL_BUTTON}}",
            handler: this._close,
            scope: this
        };
        
        this._box = Ext.create('Ametys.window.DialogBox', {
            title: dialogTitle,
            iconCls: dialogIconCls,
            
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            width: 600,
            items: [ this._form ],
           
            closeAction: 'destroy',
            defaultFocus: this._form,
            
            referenceHolder: true,
            defaultButton: 'okButton',
            
            buttons : [okButton, cancelButton],
            
            listeners: {
                resize: this._onResize,
                scope: this
            }
        });
        
        this._configureForm();
    },
    
    /**
     * @private
     * Configures the {@link Ametys.form.ConfigurableFormPanel} of the dialog box
     */
    _configureForm: function ()
    {
        // Retrieve the info needed by some fields
        Ametys.data.ServerComm.callMethod({
            role: "org.ametys.plugins.extraction.edition.EditExtractionNodeManager",
            methodName: "getNodeEditionConfiguration",
            parameters: [],
            callback: {
                handler: this._configureFormCb,
                scope: this
            },
            errorMessage: {
                category: this.self.getName(),
                msg: "{{i18n PLUGINS_EXTRACTION_EDIT_NODE_ERROR_MSG}}"
            }
        });
    },
    
    /**
     * @private
     * Callback for form configuration
     * @param {Object} response needed information to configure form
     */
    _configureFormCb: function(response)
    {
        var configuration = this._getFormConfiguration(response);
        
        this._form.configure(configuration);
        
        this._initForm ();
        this._box.show();
    },
    
    /**
     * @private
     * Initialize the fields of the form
     */
    _initForm: function ()
    {
        var form = this._form.getForm();
        
        if (this._mode == 'new') 
        {
            this._form.setValues(this._getInitFormCreationValues());
        }
        else
        {
            this._form.setValues(this._getInitFormEditionValues());
        }
    },
    
    /**
     * @protected
     * Retrieves the values to set to init form on creation mode
     * @return {Object} the values to set to init form
     */
    _getInitFormCreationValues: function()
    {
        return {};
    },
    
    /**
     * @protected
     * Retrieves the values to set to init form on edition mode
     * @return {Object} the values to set to init form
     */
    _getInitFormEditionValues: function()
    {
        return {
            values: Ext.apply({}, this._data),
            repeaters: []
        };
    },
    
    /**
     * @protected
     * Called when one of the fields changes after the form is ready
     */
    _onFieldChanged: function(field)
    {
        this._hasModifiedFields = true;
    },
    
    /**
     * @protected
     * Called when the form renders
     */
    _onResize: function()
    {
        this._form.updateLayout();
    },
    
    /**
     * @private
     * Call the callback if the form is valid
     */
    _onOk: function()
    {
        if (this._form && !this._form.isValid())
        {
            return;
        }
            
        // FIXME EXTRACT-40 Edit extraction node: edit with no modification should not set the tool to dirty
        if (/*this._hasModifiedFields && */Ext.isFunction(this._callback))
        {
            var values = this._getFormValues();
            this._callback(values);
        }
        
        this._close();
    },
    
    /**
     * @protected
     * Gets the values of the form
     * @return {Object} The form values
     */
    _getFormValues: function()
    {
        return this._form.getValues(undefined, undefined, undefined, true);
    },
    
    /**
     * @private
     * Close the dialog box
     */
    _close: function()
    {
        this._box.close();
        this._box = null;
        this._form = null;
    }
 });