/*
 *  Copyright 2024 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 to query and select one right.
 * To facilitate the selection of a right. It's possible to restrict the list of
 * right by selecting a profile
 */
Ext.define('Ametys.form.field.RightByProfile', {
    extend: 'Ametys.form.AbstractFieldsWrapper',
    
    statics: 
    {
        /**
         * @readonly
         * @protected
         * @property {String} ALL_PROFILES value of the profile combobox to ignore filtering by profile
         */
        ALL_PROFILES: "#ALL#",
        
        /**
         * @readonly
         * @property {String} READER_PROFILE id of the reader profile
         */
        READER_PROFILE: "READER"
    },
    
    /**
     * @cfg {boolean} [showProfilesIncludingRight=false] true to display a line 
     * of text below the selectors to list all the profile including the selected
     * right
     */
    
    /**
     * @private
     * @property {Ext.data.Store} _profileStore The store of the profile combobox
     */
    initComponent: function()
    {
        var rightCfg = {
                xtype: 'edition.right',
                itemId: 'select-right',
                cls: 'ametys',
                includeReader: true,
                allowBlank: this.allowBlank,
                flex: 2
        }
        
        var selectors = [
            {
                xtype: 'combobox',
                itemId: 'select-profile',
                editable: false,
                queryMode: "local", // remote is useless on non editable field
                value: Ametys.form.field.RightByProfile.ALL_PROFILES,
                forceSelection: true,
                cls: 'ametys',
                flex: 1,
                maxWidth: 120,
                valueField: "id",
                displayField: "label",
                store: this._createProfileStore(),
                listeners: {
                    change: this._onProfileChange,
                    scope: this
                },
                listConfig: {
                    getInnerTpl: function(displayField) {
                        return '{[Ext.String.escapeHtml(values.' + displayField + ')]}';
                    }
                }
            },
            rightCfg
        ];
        
        this.items = [{
            xtype: 'container',
            layout: {
                type: 'hbox',
                align: 'stretch'
            },
            items : selectors
        }, {
            padding: "2 0 0 0",
            html: "",
            visible: false,
        }];
        this.layout = {
            type: 'vbox',
            align: 'stretch'
        };
        
        this._includedTpl = new Ext.XTemplate(
            '{{i18n PLUGINS_CORE_UI_WIDGET_RIGHT_BY_PROFILE_CONTAINING_PROFILE}}',
            '<tpl for="." between=", "><strong>{.}</strong></tpl>'
        );

        this.callParent(arguments);
    },
    
    getValue: function()
    {
        return this.items.get(0).getComponent('select-right').getValue();
    },
    
    setValue: function(value)
    {
        return this.items.get(0).getComponent('select-right').setValue(value);
    },
    
    /**
     * @private
     * @return {Ext.data.Store} A newly created store for the profile
     */
    _createProfileStore: function()
    {
        this._profileStore = Ext.create('Ext.data.Store', {
            autoDestroy: true,
            autoLoad: true,
            proxy: {
                type: 'ametys',
                plugin: 'core',
                url: 'rights/profiles.json',
                extraParams: {
                    limit: null, // No pagination
                    context: this._getContext()
                },
                reader: {
                    type: 'json',
                    rootProperty: 'profiles'
                }
             },
            fields: [
                {name: 'id'},
                {name: 'label', type: 'string'},
                {name: 'rights'}
            ],
            sorters: [
                {sorterFn: function(p1, p2) {
                    if (p1.get("id") == Ametys.form.field.RightByProfile.ALL_PROFILES) { return -1; }
                    else if (p2.get("id") == Ametys.form.field.RightByProfile.ALL_PROFILES) { return 1; }
                    else { return 0; }
                }},
                {property: 'label', direction: 'ASC'}
            ],
            listeners: {
                'load': {
                    scope: this,
                    fn: function(store) {
                        // Add a select all option
                        store.add({id: Ametys.form.field.RightByProfile.ALL_PROFILES, label: "{{i18n PLUGINS_CORE_UI_WIDGET_RIGHT_BY_PROFILE_ALL_PROFILE}}", rights: []});
                        
                        // wait for the profile store to be initialized before
                        // adding the listener on right field as it requires 
                        // to have the profile store initialized
                        if (this.showProfilesIncludingRight)
                        {
                            var rightField = this.items.get(0).getComponent('select-right');
                            rightField.on("change", this._onRightChange, this);
                            this._onRightChange(rightField, rightField.getValue());
                        }
                    }
                }
            }
        });
        return this._profileStore;
    },
    
    /**
     * @protected
     * Returns an additional context to provide to the profile store proxy.
     * @return {String} a context or ""
     */
    _getContext: function() {
        return "";
    },
    
    /**
     * @private
     * Filter the right field based on the selected profile
     */
    _onProfileChange: function(profileField, newValue, oldValue)
    {
        var rightField = this.items.get(0).getComponent('select-right');
        if (newValue == Ametys.form.field.RightByProfile.ALL_PROFILES || newValue == null)
        {
            rightField._store.removeFilter('profile');
        }
        else
        {
            var rights;
            // special case for the reader profile that should
            // include the fake reader right
            if (newValue == Ametys.form.field.RightByProfile.READER_PROFILE)
            {
                rights = [Ametys.form.widget.Right.READER_RIGHT];
            }
            else
            {
                var profile = this._profileStore.getById(newValue);
                rights = profile.get("rights");
            }
            
            if (rights.length == 1)
            {
                rightField.setValue(rights[0]);
            }
            
            rightField._store.addFilter([{
                id: "profile",
                filterFn: function(item) {
                    return Ext.Array.contains(rights, item.get("id"));
                }
            }]);
        }
    },
    
    /**
     * @private
     * Display a line of text showing all the profile containing the selected
     * right
     */
    _onRightChange: function(rightField, newValue, oldValue)
    {
        var infoBloc = this.items.get(1);
        if (newValue)
        {
            var profiles = [];
            // Special case for the reader right as the reader profile
            // does not include the fake reader right
            if (newValue == Ametys.form.widget.Right.READER_RIGHT)
            {
                var readerProfile = this._profileStore.getById(Ametys.form.field.RightByProfile.READER_PROFILE);
                profiles.push(readerProfile.get('label'));
            }
            else
            {
                this._profileStore.each(function(item) {
                    if (Ext.Array.contains(item.get('rights'), newValue))
                    {
                        profiles.push(item.get('label'));
                    }
                });
            }
            
            if (profiles.length == 0)
            {
                infoBloc.setHtml("{{i18n PLUGINS_CORE_UI_WIDGET_RIGHT_BY_PROFILE_NO_CONTAINING_PROFILE}}");
            }
            else
            {
                infoBloc.setHtml(this._includedTpl.apply(profiles.map(p => Ext.String.htmlEncode(p))));
            }
            infoBloc.setVisible(true);
        }
        else
        {
            infoBloc.setVisible(false);
        }
    }
});