/*
 *  Copyright 2022 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.
 */
 
/**
 * Helper for creating a rule or an inconditional jump;
 */
Ext.define('Ametys.plugins.forms.helper.RulesDialogHelper', {
    singleton: true,
    
    /**
     * @private
     * @property {Ext.form.Panel} _formPanel The form panel.
     */
    
    /**
     * Open the dialog box
     * @param {Object} config The configuration object
     * @param {String} config.mode The mode: 'newRule' for a question rule or 'inconditionalJump' for a page rule.
     * @param {String} config.formId The form id
     * @param {String} config.pageId The page id
     * @param {String} [config.questionId] The question id for a new rule
     * @param {Function} [config.callback] The callback function
     */
    open: function (config)
    {
        this._mode = config.mode;
        this._cbFn = config.callback;
        this._formId = config.formId;
        this._pageId = config.pageId;
        this._questionId = config.questionId;
        
        this._delayedInitialize();
        this._initForm(this._formId, this._pageId, this._questionId);
        
        this._box.show();
    },
    
    /**
     * @private
     * Creates the dialog box
     */
    _delayedInitialize: function ()
    {
        if (!this._initialized)
        {
            this._formPanel = this._createFormPanel();
            
            this._box = Ext.create('Ametys.window.DialogBox', {
                title: "{{i18n PLUGINS_FORMS_ADD_RULE_LABEL}}",
                iconCls: "ametysicon-turn-right5",
                
                width: 500,
                scrollable: false,
                
                items: [this._formPanel],
                
                defaultFocus: 'option',
                closeAction: 'hide',
                
                referenceHolder: true,
                defaultButton: 'validate',
                
                buttons: [{
                    reference: 'validate',
                    text: "{{i18n PLUGINS_FORMS_QUESTIONS_DIALOG_BUTTON_OK}}",
                    handler: Ext.bind(this._validate, this)
                }, {
                    text: "{{i18n PLUGINS_FORMS_QUESTIONS_DIALOG_BUTTON_CANCEL}}",
                    handler: Ext.bind(this._cancel, this)
                }]    
            });
            
            this._initialized = true;
        }
    },
    
    /**
     * Creates the form panel of this dialog box.
     * @return {Ext.form.Panel} The form panel
     * @private
     */
    _createFormPanel: function()
    {
        var formPanel = Ext.create('Ext.form.Panel', {
            defaults: {
                cls: 'ametys',
                labelSeparator: '',
                labelAlign: 'right',
                labelWidth: 120,
                width: '100%',
                msgTarget: 'side'
            },
            
            border: false,
            scrollable: true,
            
            items: [
                {
                    xtype: 'hidden',
                    name: 'id'
                },
                {
                    xtype: 'combo',
                    name: 'option',
                    itemId: 'option',
                    fieldLabel: "{{i18n PLUGINS_FORMS_BRANCH_RULES_CHOOSE}}",
                    allowBlank: false,
                    width: 400,
                    
                    store: {
                        fields: ['value', 'displayText']
                    },
                    valueField: 'value',
                    displayField: 'displayText',
                    queryMode: 'local',
                    forceSelection : true,
                    triggerAction: 'all'
                },
                {
                    xtype: 'component',
                    itemId: 'rules-hint',
                    cls: 'rules-hint',
                    html: "{{i18n PLUGINS_FORMS_BRANCH_RULES_THEN}}"
                },
                {
                    xtype: 'radio',
                    name: 'rule',
                    cls: 'rules-radio',
                    inputValue: 'JUMP',
                    fieldLabel: ' ',
                    boxLabel: "{{i18n PLUGINS_FORMS_BRANCH_RULES_JUMP}}",
                    width: 245,
                    checked: true,
                    listeners: {'change': Ext.bind(this._onCheckJump, this)}
                },
                {
                    xtype: 'combo',
                    name: 'page',
                    hideLabel: true,
                    allowBlank: false,
                    width: 120,
                    
                    store: {
                        fields: ['value', 'displayText']
                    },
                    valueField: 'value',
                    displayField: 'displayText',
                    queryMode: 'local',
                    forceSelection : true,
                    triggerAction: 'all'
                },
                {
                    xtype: 'radio',
                    name: 'rule',
                    cls: 'rules-radio',
                    inputValue: 'FINISH',
                    fieldLabel: ' ',
                    boxLabel: "{{i18n PLUGINS_FORMS_BRANCH_RULES_FINISH}}",
                    width: 300
                }
            ]
            
        });
        
        return formPanel;
    },
    
    /**
     * Disables/enables the 'page' field depending on the 'rule' field check status.
     * @param {Ext.form.field.Field} field The field
     * @param {Object} newValue The new value
     * @param {Object} oldValue The original value
     * @private
     */
    _onCheckJump: function(field, newValue, oldValue)
    {
        var form = this._formPanel.getForm();
        if (newValue)
        {
            form.findField('page').enable();
        }
        else
        {
            form.findField('page').disable();
            form.findField('page').clearInvalid();
        }
    },
    
    /**
   * @private
   * Handler for the 'ok' button of the dialog box
   */
   _validate: function ()
   {
       var form = this._formPanel.getForm();
       if (!form.isValid())
       {
        return;
       }
       
       var values = form.getValues();
        
        if (this._mode == 'newRule')
        {
            var params = [values.id, values.option, values.rule, values.page];
            Ametys.plugins.forms.dao.FormQuestionDAO.addPageRule(params, this._validateCb, {scope: this, arguments: [values.id]} );
        }
        else
        {
            var params = [values.id, values.rule, values.page];
            Ametys.plugins.forms.dao.FormPageDAO.addRule(params, this._validateCb, {scope: this, arguments: [values.id]} );
        }
   },
    
    /**
     * Callback function called after adding rule
     * @private
     */
    _validateCb: function (response, args)
    {
        if (!response['error'])
        {
            this._box.close();
            if (Ext.isFunction (this._cbFn))
            {
                this._cbFn (args[0]);
            }
        }
    },
    
    /**
     * @private
     * Callback for the "cancel" button of the dialog. Close the dialog.
     */
    _cancel: function ()
    {
        this._box.close();
    },
    
    /**
     * @private
     * Initializes the form with some optional values.
     * @param {String} formId The form id
     * @param {String} pageId The page id
     * @param {String} [questionId] The question id for a rule.
     */
    _initForm: function (formId, pageId, questionId)
    {
        var form = this._formPanel.getForm();
        form.reset();
        
        if (this._mode === "newRule") 
        {
            this._box.setTitle("{{i18n PLUGINS_FORMS_ADD_RULE_LABEL}}");
            
            form.findField('id').setValue(questionId);
            form.findField('option').enable();
            form.findField('option').show();
            this._box.down('#rules-hint').update("{{i18n PLUGINS_FORMS_BRANCH_RULES_THEN}}");
            form.findField('rule').setValue('JUMP');
            
            // Load options
            this._loadOptions(questionId);
            form.findField('option').setValue('');
            form.findField('option').clearInvalid();
        }
        else // this._mode == 'inconditionalJump'
        {
            this._box.setTitle("{{i18n PLUGINS_FORMS_BRANCH_INCONDITIONAL_JUMP}}");
            
            form.findField('id').setValue(pageId);
            this._box.down('#rules-hint').update("{{i18n PLUGINS_FORMS_BRANCH_INCONDITIONAL_JUMP_NO_RULE}}");
            form.findField('rule').setValue('JUMP');
            
            // Disable the option field
            form.findField('option').disable();
            form.findField('option').hide();
        }
        
        // Load pages
        this._loadPages(formId, pageId);
        form.findField('page').setValue('');
        form.findField('page').clearInvalid();
    },
    
    /**
     * Loads the options of a given question.
     * @param {String} questionId The question id.
     * @private
     */
    _loadOptions: function(questionId)
    {
        Ametys.data.ServerComm.callMethod({
            role: "org.ametys.plugins.forms.dao.FormQuestionDAO",
            methodName: "getChoiceListQuestionOptions",
            parameters: [questionId],
            callback: {
                scope: this,
                handler: Ext.bind(this._loadOptionsCb, this),
            }
        });
    },
    
    /**
     * Loads the options of a given question. Called by {@link #_loadOptions}.
     * @param {Object} options The question options
     * @private
     */
    _loadOptionsCb: function(options)
    {
        var form = this._formPanel.getForm();
        var store = form.findField('option').getStore();
        store.removeAll();
        
        for (var key in options)
        {
            store.add({
                value: key,
                displayText: options[key]
            });
        }
    },
    
    /**
     * Loads the pages (placed after a certain page) of a given form.
     * @param {String} formId The form id
     * @param {String} pageId The page id. We only load the pages after this one.
     * @private
     */
    _loadPages: function(formId, pageId)
    {
        Ametys.plugins.forms.dao.FormPageDAO.getChildPages([formId], this._loadPagesCb, {scope: this, arguments: [pageId]});
    },
    
    /**
     * Loads the pages (placed after a certain page) of a given form. Called by {@link #_loadPages}.
     * @param {Object} pages The pages object
     * @param {Array} args The callback arguments
     * @param {String} args.pageId The page id. We only load the pages after this one.
     * @private
     */
    _loadPagesCb: function(pages, args)
    {
        var pageId = args[0]
        
        var form = this._formPanel.getForm();
        var store = form.findField('page').getStore();
        store.removeAll();
        
        var isNextPages = false;
        for (var i = 0; i < pages.length; i++) {
            var value = pages[i].id
            if (isNextPages)
            {
                store.add({
                    value: value,
                    displayText: pages[i].title
                });
            }
            
            if (pageId == value)
            {
                isNextPages = true;
            }
        }
    }
    
});