/*
 *  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 defining actions related to the ODF root
 * @private
 */
Ext.define('Ametys.plugins.odf.web.root.ODFRootActions', {
    singleton: true,
    
    /**
     * @private
     * @property {Boolean} _initialized Indicates if the dialog box has been initialized
     */
    
    /**
     * @private
     * @property {Ametys.form.ConfigurableFormPanel} _formPanel The form panel
     */
    
    /**
     * @private
     * @property {Ametys.window.DialogBox} _box The dialog box
     */
    
    /**
     * @private
     * @property {String} _pageId Identifier of the current page
     */
    /**
     * @private
     * @property {String} _defaultFirstLevel The default value for the first level combo
     */
    /**
     * @private
     * @property {String} _defaultSecondLevel The default value for the second level combo
     */
    /**
     * @private
     * @property {Ametys.ribbon.element.ui.ButtonController} _controller The button controller that initialized the action
     */
    
    /**
     * @private
     * @property {Object} _rootPageInfo Object containing the info related to the odf root status of the current page
     */
    
    /**
     * Action function to be called by the controller.
     * Allow an user to add or remove an ODF root from the current page
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    addOrRemove: function (controller)
    {
        var pageTarget = controller.getMatchingTargets()[0],
            pageId;
            
        if (pageTarget)
        {
            pageId = pageTarget.getParameters().id;
            
            controller.serverCall('getOdfRootPageInfo', [pageId], Ext.bind(this._getPageInfoCb, this), {
                errorMessage: true, 
                arguments: {
                    pageId: pageId,
                    defaultFirstLevel: controller.getInitialConfig('default-first-level'),
                    defaultSecondLevel: controller.getInitialConfig('default-second-level'),
                    controller: controller
                }
            });
        }
    },
    
    /**
     * Callback once root page properties are retrieved
     * @param {Object} properties the root page properties
     * @param {Object} arguments The callback arguments
     */
    _getPageInfoCb: function(properties, arguments)
    {
        if (properties.noCatalog === true)
        {
            Ametys.Msg.show({
                title: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_TITLE}}",
                msg: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_NO_CATALOG}}",
                buttons: Ext.Msg.OK,
                icon: Ext.Msg.ERROR
            });
            
            return;
        }
        
        this._pageId = arguments.pageId;
        this._defaultFirstLevel = arguments.defaultFirstLevel;
        this._defaultSecondLevel = arguments.defaultSecondLevel;
        this._controller = arguments.controller;
        this._rootPageInfo = properties;
        
        this._createDialogBox(properties);
        this._initForm();
    },
    
    /**
     * @private
     * Create the dialog box if necessary
     * @param {Object} properties Properties for the different field of the dialogbox
     */
    _createDialogBox: function(properties)
    {
        if (this._initialized)
        {
            return;
        }
        
        this._form = Ext.create('Ext.form.Panel', {
            border: false,
            
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            
            defaults: {
                cls: 'ametys',
                labelWidth: 170,
                labelAlign: 'right',
                labelSeparator: '',
                msgTarget: 'side'
            },
            
            items: this._getFormItemsCfg(properties)
        });
        
        this._box = Ext.create('Ametys.window.DialogBox', {
            title: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHOICE_TITLE}}",
            iconCls: 'ametysicon-website38 decorator-odficon-blackboard',
            
            width: 530,
            
            items : [ this._form ],
            
            referenceHolder: true,
            // FIXME default button does not seems to work...
            defaultButton: 'validate',
            closeAction: 'hide',
            
            buttons : [{
                reference: 'validate',
                text : "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHOICE_OK_BUTTON}}",
                handler : this._validate,
                scope: this
            }, {
                reference: 'remove',
                text: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHOICE_DELETE_BUTTON}}",
                disabled: true,
                handler: this._remove,
                scope: this
            }, {
                reference: 'cancel',
                text :"{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHOICE_CANCEL_BUTTON}}",
                handler: this._cancel,
                scope: this
            }]
        });
        
        this._initialized = true;
        return;
    },
    
    /**
     * Provide the items configuration of the form panel
     * @param {Object} properties Properties for the different field of the dialogbox
     * @return {Object/Object[]} the items configuration of the form panel
     */
    _getFormItemsCfg: function(properties)
    {
        var catalogStore = this._getCatalogStoreCfg(),
            firstLevelStore = this._getLevelStoreCfg(Ext.bind(this._onFirstLevelLoad, this)),
            secondLevelStore = this._getLevelStoreCfg(Ext.bind(this._onSecondLevelLoad, this));
        
        return [{
            xtype: 'component',
            cls: 'a-text',
            html: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHOOSE_CATALOG}}"
        }, {
            xtype: 'combobox',
            reference: 'catalog',
            name: 'catalog',
            fieldLabel: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHOICE_CATALOG}}",
            ametysDescription: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHOICE_CATALOG_DESC}}",
            
            editable: false,
            forceSelection: true,
            allowBlank: false,
            
            queryMode: 'local',
            
            valueField: 'code',
            displayField: 'label',
            
            store: catalogStore
        }, {
            xtype: 'component',
            cls: 'a-text',
            html: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_LEVEL_HINT}}"
        }, {
            xtype: 'combobox',
            reference: 'firstLevel',
            name: 'firstLevel',
            fieldLabel: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHOICE_FIRST_LEVEL}}",
            ametysDescription: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHOICE_FIRST_LEVEL_DESC}}",
            
            editable: false,
            forceSelection: true,
            
            queryMode: 'local',
            
            valueField: 'name',
            displayField: 'label',
            
            store: firstLevelStore,
            
            listeners: {'change': {fn: this._onFirstLevelChange, scope: this}}
        }, {
            xtype: 'combobox',
            reference: 'secondLevel',
            name: 'secondLevel',
            fieldLabel: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHOICE_SECOND_LEVEL}}",
            ametysDescription: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHOICE_SECOND_LEVEL_DESC}}",
            
            editable: false,
            forceSelection: true,
            
            queryMode: 'local',
            
            valueField: 'name',
            displayField: 'label',
            
            store: secondLevelStore,
            
            listeners: {'change': {fn: this._onSecondLevelChange, scope: this}}
        }, {
            xtype: 'component',
            cls: 'a-text',
            html: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHILDREN_INDEXATION}}"
        }, {
            xtype: "checkbox",
            fieldLabel: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_ARE_CHILDREN_INDEXABLE}}",
            ametysDescription: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CHILDREN_INDEXATION}}",
            reference: 'areChildrenIndexable',
            name: 'areChildrenIndexable',
			/*style: {
				marginLeft: '125px'
			}*/
        }]
    },
    
    /**
     * Catalog store config getter
     * @return {Object} the catalog store config
     */
    _getCatalogStoreCfg: function()
    {
        return {
            type: 'store',
            proxy: {
                type: 'ametys',
                plugin: 'odf-web',
                url: 'catalogs/list.json',
                reader: {
                    type: 'json'
                }
            },
            fields: [
                'code',
                {name: 'label', type: 'string'}
            ],
            sortOnLoad: true,
            sorters: [{property: 'label', direction:'ASC'}],
            
            listeners: {
                'beforeload': Ext.bind(this._onCatalogBeforeLoad, this),
                'load': Ext.bind(this._onCatalogLoad, this)
            }
        }
    },
    
    /**
     * Lvel store config getter
     * @param {Function} loadListener A specific load listener for the store
     * @return {Object} the level store config
     */
    _getLevelStoreCfg: function(loadListener)
    {
        return {
            type: 'store',
            proxy: {
                type: 'ametys',
                plugin: 'odf-web',
                url: 'eligible-metadata/list.json',
                reader: {
                    type: 'json'
                }
            },
            fields: [
                'name',
                {name: 'label', type: 'string'}
            ],
            sortOnLoad: true,
            sorters: [{property: 'label', direction:'ASC'}],
            
            listeners: {
                'load': loadListener
            }
        }
    },
    
    /**
     * @private
     * Listener when first level has changed
     * @param {Ext.form.field.ComboBox} field the field
     * @param {String} newValue the new value
     * @param {String} oldValue the old value
     */
    _onFirstLevelChange: function(field, newValue, oldValue)
    {
        var secondLevelValue = this._form.getForm().findField('secondLevel').getValue();
        
        if (!Ext.isEmpty(newValue))
        {
            if (newValue == secondLevelValue)
            {
                field.markWarning("{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_SAME_LEVELS_WARN}}");
            }
            else
            {
                field.clearWarning();
            }
        }
        else
        {
            field.clearWarning();
        }
    },
    
    /**
     * @private
     * Listener when second level has changed
     * @param {Ext.form.field.ComboBox} field the field
     * @param {String} newValue the new value
     * @param {String} oldValue the old value
     */
    _onSecondLevelChange: function(field, newValue, oldValue)
    {
        if (!Ext.isEmpty(newValue))
        {
	        var firstLevelValue = this._form.getForm().findField('firstLevel').getValue();
            if (newValue == firstLevelValue)
            {
                field.markWarning("{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_SAME_LEVELS_WARN}}");
            }
            else
            {
                field.clearWarning();
            }
        }
        else
        {
            field.clearWarning();
        }
    },
    
    /**
     * @private
     * Initialize the box form
     */
    _initForm: function ()
    {
        this._form.reset();
        
        // remove button status
        this._box.lookupReference('remove').setDisabled(this._rootPageInfo.isOdfRootPage !== true);
        
        this._box.lookupReference('catalog').getStore().load();
        this._box.lookupReference('firstLevel').getStore().load();
        this._box.lookupReference('secondLevel').getStore().load();
        this._box.lookupReference('areChildrenIndexable').setValue(this._rootPageInfo.areChildrenIndexable);
    },
    
    /**
     * @private
     * Called before the catalog store is loaded in order to set the current page id for the load request.
     * @param {Ext.data.Store} store The catalog store
     * @param {Ext.data.operation.Operation} operation The Ext.data.operation.Operation object that will be passed to the Proxy to load the Store
     */
    _onCatalogBeforeLoad: function(store, operation)
    {
        var params = operation.getParams() || {};
        
        operation.setParams(Ext.apply(params, {
            id: this._pageId
        }));
    },
    
    /**
     * @private
     * Called whenever the catalog store reads the remote data.
     * Used to update the catalog field state (value, disabled...)
     * @param {Ext.data.Store} store The catalog store
     * @param {Ext.data.Model[]} records An array of records
     * @param {Boolean} successful True if the operation was successful
     */
    _onCatalogLoad: function(store, records, successful)
    {
        var catalogField = this._box.lookupReference('catalog');
        
        catalogField.setReadOnly(true);
        
        if (!successful)
        {
            return;
        }
        
        if (records.length == 0)
        {
            Ametys.Msg.show({
                title: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_TITLE}}",
                msg: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_NO_MORE_ADD}}",
                buttons: Ext.Msg.OK,
                icon: Ext.Msg.INFO
            });
            
            return;
        }
        
        if (records.length == 1)
        {
            catalogField.setValue(records[0].get('code'));
        }
        else
        {
            catalogField.setReadOnly(false); // enable the field
            
            if (this._rootPageInfo.isOdfRootPage === true)
            {
                catalogField.setValue(this._rootPageInfo.catalog);
            }
        }
        
        // box is shown once catalog list is correct
        this._box.show();
    },
    
    /**
     * @private
     * Called whenever the level store reads the remote data.
     * Used to update the catalog field state (value, disabled...)
     * @param {Ext.data.Store} store The catalog store
     * @param {Ext.data.Model[]} records An array of records
     * @param {Boolean} successful True if the operation was successful
     */
    _onFirstLevelLoad: function(store, records, successful)
    {
        if (!successful)
        {
            return;
        }
        
        store.add({name: '', label: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_NONE_OPTION}}"});
        
        var firstLevel = this._box.lookupReference('firstLevel');
        if (this._rootPageInfo.isOdfRootPage === true)
        {
            firstLevel.setValue(this._rootPageInfo.firstLevel);
        }
        else
        {
            firstLevel.setValue(this._defaultFirstLevel);
        }
    },
    
    /**
     * @private
     * Called whenever the level store reads the remote data.
     * Used to update the catalog field state (value, disabled...)
     * @param {Ext.data.Store} store The catalog store
     * @param {Ext.data.Model[]} records An array of records
     * @param {Boolean} successful True if the operation was successful
     */
    _onSecondLevelLoad: function(store, records, successful)
    {
        if (!successful)
        {
            return;
        }
        
        store.add({name: '', label: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_NONE_OPTION}}"});
        
        var secondLevel = this._box.lookupReference('secondLevel');
        if (this._rootPageInfo.isOdfRootPage === true)
        {
            secondLevel.setValue(this._rootPageInfo.secondLevel);
        }
        else
        {
            secondLevel.setValue(this._defaultSecondLevel);
        }
    },
    
    /**
    * @private
    * Validate button handler function
    */
    _validate: function()
    {
        var form = this._form.getForm();
        if (!form.isValid())
        {
            return;
        }
        
        var values = form.getValues();
        
        if (values.secondLevel != "" && values.firstLevel == "")
    	{
        	form.findField('firstLevel').markInvalid("{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_NO_FIRST_LEVEL_ERROR}}");
        	return;
    	}
        
        Ametys.MessageBox.show({
            title: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_LABEL}}", 
            message: "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_CONFIRM}}",
            buttons: Ext.Msg.YESNO,
            icon: Ext.Msg.WARNING,
            fn: function (btn) {
                if (btn == 'yes')
                {
                    var values = form.getValues();
                    var params = [
                        this._pageId, 
                        values.catalog,
                        values.firstLevel,
                        values.secondLevel,
                        values.areChildrenIndexable == 'on'
                    ];
                
                    this._controller.serverCall('addOrUpdateOdfRootProperty', params, Ext.bind(this._successCb, this), {
                        waitMessage: this._box, 
                        errorMessage: true,
                        priority: Ametys.data.ServerComm.PRIORITY_LONG_REQUEST
                    }); 
                }
           }, 
           scope: this
        });
        
        
    },
    
    /**
    * @private
    * remove button handler function
    */
    _remove: function()
    {
        Ametys.Msg.confirm(
            "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_DELETE_TITLE}}",
            "{{i18n plugin.odf-web:PLUGINS_ODFWEB_ODF_ROOT_PAGE_DELETE_CONFIRM}}",
            this._removeAfterConfirm,
            this
        );
    },
    
    /**
     * Callback called after the user confirm or cancel the remove action
     * @private
     * @param {String} answer 'yes' if the user confirmed the remove action
     */
    _removeAfterConfirm: function(answer)
    {
        if (answer == 'yes')
        {
            this._controller.serverCall('removeOdfRootPage', [this._pageId], Ext.bind(this._successCb, this), {
                waitMessage: this._box, 
                errorMessage: true 
            });
        }
    },
    
    
    /**
     * @private
     * Success callback function, called after a validate or remove operation
     * @param {Object} response The server response
     * @param {Object} arguments The arguments
     */
    _successCb: function()
    {
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.MODIFIED,
            parameters: {major: true},
            targets: [{
                id: Ametys.message.MessageTarget.PAGE,
                parameters: {
                    ids: [this._pageId]
                }
            }]
        });
        
        this._box.close();
    },
     
    /**
     * The cancel button handler
     * @private
     */
    _cancel: function()
    {
        this._box.close();
    }
});