/*
 *  Copyright 2018 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 class allows to generate a RNCP sheet with dynamic fields.
 */
Ext.define('Ametys.odf.rncp.ExportRNCP', {
    singleton: true,
    
    /**
     * @property {Ametys.window.DialogBox} _box The dialog to generate the RNCP sheet containing a form.
     * @private
     */
    
    /**
     * Generate a RNCP sheet for the selected subprogram.
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    generateForSubProgram: function(controller)
    {
        var labels = {
            title:          '{{i18n plugin.odf:PLUGINS_ODF_RNCP_SUBPROGRAM_DIALOG_TITLE}}',
            intro:          '{{i18n plugin.odf:PLUGINS_ODF_RNCP_SUBPROGRAM_DIALOG_INTRO}}',
            modelLabel:     '{{i18n plugin.odf:PLUGINS_ODF_RNCP_SUBPROGRAM_DIALOG_FIELD_MODEL_LABEL}}',
            modelDesc:      '{{i18n plugin.odf:PLUGINS_ODF_RNCP_SUBPROGRAM_DIALOG_FIELD_MODEL_DESC}}',
            buttonOK:       '{{i18n plugin.odf:PLUGINS_ODF_RNCP_SUBPROGRAM_DIALOG_BUTTON_OK}}',
            buttonCancel:   '{{i18n plugin.odf:PLUGINS_ODF_RNCP_SUBPROGRAM_DIALOG_BUTTON_CANCEL}}',
            errorTitle:     '{{i18n plugin.odf:PLUGINS_ODF_RNCP_SUBPROGRAM_DIALOG_ERROR_TITLE}}',
            errorComboBox:  '{{i18n plugin.odf:PLUGINS_ODF_RNCP_SUBPROGRAM_DIALOG_ERROR_EMPTY_COMBOBOX}}'
        };
        
        var contentId = controller.getMatchingTargets()[0].getParameters().id;
        var programComboBox = this._createComboBox(
            'program',
            '{{i18n plugin.odf:PLUGINS_ODF_RNCP_SUBPROGRAM_DIALOG_FIELD_PROGRAM_LABEL}}',
            '{{i18n plugin.odf:PLUGINS_ODF_RNCP_SUBPROGRAM_DIALOG_FIELD_PROGRAM_DESC}}',
            this._getAvailableProgramsProxyCfg(controller, contentId)
        );
        
        this._createDialogBox(controller, labels, [programComboBox]);
    },
    
    /**
     * Generate a RNCP sheet for the selected program.
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    generateForProgram: function(controller)
    {
        var labels = {
            title:          '{{i18n plugin.odf:PLUGINS_ODF_RNCP_PROGRAM_DIALOG_TITLE}}',
            intro:          '{{i18n plugin.odf:PLUGINS_ODF_RNCP_PROGRAM_DIALOG_INTRO}}',
            modelLabel:     '{{i18n plugin.odf:PLUGINS_ODF_RNCP_PROGRAM_DIALOG_FIELD_MODEL_LABEL}}',
            modelDesc:      '{{i18n plugin.odf:PLUGINS_ODF_RNCP_PROGRAM_DIALOG_FIELD_MODEL_DESC}}',
            buttonOK:       '{{i18n plugin.odf:PLUGINS_ODF_RNCP_PROGRAM_DIALOG_BUTTON_OK}}',
            buttonCancel:   '{{i18n plugin.odf:PLUGINS_ODF_RNCP_PROGRAM_DIALOG_BUTTON_CANCEL}}',
            errorTitle:     '{{i18n plugin.odf:PLUGINS_ODF_RNCP_PROGRAM_DIALOG_ERROR_TITLE}}',
            errorComboBox:  '{{i18n plugin.odf:PLUGINS_ODF_RNCP_PROGRAM_DIALOG_ERROR_EMPTY_COMBOBOX}}'
        };
        
        this._createDialogBox(controller, labels, []);
    },
    
    /**
     * Get the common form items.
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller
     * @param {String[]} labels The i18n translated labels
     * @return {Ext.form.field.Base[]} An array with the common form items
     * @private
     */
    _getCommonFormItems: function(controller, labels)
    {
        var formItems = [];
        
        formItems.push(this._createComboBox(
            'model',
            labels.modelLabel,
            labels.modelDesc,
            this._getModelsProxyCfg(controller)
        ));
        
        var contentId = controller.getMatchingTargets()[0].getParameters().id;
        formItems.push({
            xtype: 'hidden',
            itemId: 'id',
            reference: 'id',
            name: 'id',
            value: contentId
        });
        
        return formItems;
    },
    
    /**
     * Create and display the dialog box.
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     * @param {String[]} labels The i18n translated labels
     * @param {Ext.form.field.Base[]} specificFormItems The additional form items for this instance of the dialog.
     * @private
     */
    _createDialogBox: function(controller, labels, specificFormItems)
    {
        var formItems = [];
        Ext.Array.push(formItems, specificFormItems);
        Ext.Array.push(formItems, this._getCommonFormItems(controller, labels));
        
        var formPanel = Ext.create('Ext.form.FormPanel', {
            itemId: 'form',
            defaultFieldConfig: {
                labelWidth: 250
            },
            scrollable: true,
            flex: 1,
            items: formItems
        });
        
        this._box = Ext.create('Ametys.window.DialogBox', {
            title: labels.title,
            iconCls: 'ametysicon-docx',
            
            width: 550,
            layout: {
                type: "vbox",
                align: "stretch"
            },
            
            defaultFocus: 'form',
            items: [{
                xtype: 'component',
                html: labels.intro
            }, formPanel],
            
            referenceHolder: true,
            defaultButton: 'validate',
            closeAction: 'destroy',
            
            buttons:  [{
                reference: 'validate',
                itemId: 'button-validate',
                text: labels.buttonOK,
                handler: validate,
                scope: this
            }, {
                itemId: 'button-cancel',
                text: labels.buttonCancel,
                handler: this._close,
                scope: this
            }]
        })
        .show();
        
        function validate()
        {
            if (formPanel.isValid())
            {
                var formValues = formPanel.getValues();
                
                var args = {};
                for (var paramName in formValues)
                {
                    args[paramName] = formValues[paramName];
                }
                
                Ametys.openWindow(Ametys.getPluginDirectPrefix('odf') + controller.getInitialConfig('exportURL'), args);
                
                this._close();
            }
            else
            {
                var invalidFields = Ext.Array.filter(formPanel.getFieldNames(), function(fieldName) {
                    return !formPanel.getField(fieldName).isValid();
                });
                if (invalidFields.length > 0)
                {
                    formPanel.getField(invalidFields[0]).focus();
                }
            }
        }
    },
    
    /**
     * Close the dialog.
     * @private
     */
    _close: function()
    {
        this._box.close();
    },
    
    /**
     * Create a combo box with a proxy store.
     * @param {String} id The ID
     * @param {String} label The label
     * @param {String} description The description
     * @param {Object} proxyCfg The proxy configuration
     * @param {String[]} labels The i18n translated labels
     * @return {Ext.form.field.ComboBox} The created combobox
     * @private
     */
    _createComboBox: function(id, label, description, proxyCfg, labels)
    {
        var comboBox = Ext.create('Ext.form.field.ComboBox', {
            reference: id,
            name: id,
            fieldLabel: label,
            ametysDescription: description,
            editable: false,
            forceSelection: true,
            allowBlank: false,
            queryMode: 'local',
            valueField: 'id',
            displayField: 'label'
        });
        
        comboBox.setStore(this._getStoreCfg(proxyCfg, comboBox, labels));
        return comboBox;
    },
    
    /**
     * Get the store configuration from a proxy configuration.
     * @param {Object} proxyCfg The proxy configuration
     * @param {Ext.form.field.ComboBox} comboBox The combobox to edit
     * @param {String[]} labels The i18n translated labels
     * @return {Object} The store configuration
     * @private
     */
    _getStoreCfg: function(proxyCfg, comboBox, labels)
    {
        return {
            autoLoad: true,
            type: 'store',
            proxy: proxyCfg,
            sortOnLoad: true,
            sorters: [{property: 'label', direction:'ASC'}],
            listeners: {
                'load': Ext.bind(this._onComboBoxLoad, this, [comboBox, labels], 0)
            }
        };
    },
    
    /**
     * Get the proxy store configuration to get available export RNCP models.
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     * @return {Object} An object representing a proxy store configuration
     * @private
     */
    _getModelsProxyCfg: function(controller)
    {
        return {
            type: 'ametys',
            serverCaller: controller,
            methodName: 'getModels',
            methodArguments: [],
            reader: {
                type: 'json'
            }
        };
    },
    
    /**
     * Get the proxy store configuration to get available programs for the current subprogram.
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     * @param {String} contentId The content ID
     * @return {Object} An object representing a proxy store configuration
     * @private
     */
    _getAvailableProgramsProxyCfg: function(controller, contentId)
    {
        return {
            type: 'ametys',
            serverCaller: controller,
            methodName: 'getAvailablePrograms',
            methodArguments: ['contentId'],
            extraParams: {
                contentId: contentId
            },
            reader: {
                type: 'json'
            }
        };
    },
    
    /**
     * Listener when the store is loaded
     * @param {Ext.form.field.ComboBox} comboBox The combobox field on which the store is based
     * @param {String[]} labels The i18n translated labels
     * @param {Ext.data.Store} store The store loaded
     * @param {Ext.data.Model[]} records An array of records
     * @param {Boolean} successful True if the operation was successful.
     * @private
     */
    _onComboBoxLoad: function(comboBox, labels, store, records, successful)
    {
        if (!successful)
        {
            return;
        }
        
        if (records.length == 0)
        {
            Ametys.Msg.show({
                title: labels.errorTitle,
                msg: Ext.String.format(labels.errorComboBox, comboBox.getFieldLabel()),
                buttons: Ext.Msg.OK,
                icon: Ext.Msg.INFO
            });
            
            this._close();
            return;
        }
        
        if (records.length == 1)
        {
            comboBox.setValue(records[0].get('id'));
        }
    }
});