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

/**
 * Tool to display the result of all relevant AccessController for the context
 */

Ext.define('Ametys.plugins.coreui.rights.ExplainUserRightTool', {
    extend: "Ametys.plugins.coreui.rights.RightContextSelectionTool",
    
    /**
     * @cfg {String} showUnknowResultIconCls The separated CSS classes to apply to button to show unknown results
     */
    showUnknowResultIconCls: 'ametysicon-sign-add',
    /**
     * @cfg {String} showUnknowResultIconCls Tooltip of the button to show unknown results
     */
    showUnknowResultTooltip: "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_SHOW_UNKNOWN_RESULTS}}",

    /**
     * @cfg {String} hideUnknowResultIconCls The separated CSS classes to apply to button to hide unknown results
     */
    hideUnknowResultIconCls: 'ametysicon-sign-minus',
    /**
     * @cfg {String} hideUnknowResultIconCls Tooltip of the button to hide unknown results
     */
    hideUnknowResultTooltip: "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_HIDE_UNKNOWN_RESULTS}}",
    
    constructor: function(config)
    {
        this.callParent(arguments);
        
        // Create the result template
        this._resultTpl = new Ext.XTemplate(
            '{[this.setAnyUserMode(values.mode)]}',
            '<p><i class="icon {[this.computeGlyph(values.result)]}"></i>{[this.computeSummaryLabel(values.result)]}</p>',
            
            '<h2>{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_DETAILS_LABEL}}</h2>',
            '<tpl if="values.explanations.length != 0">',
                '<ul>',
                    '<tpl for="explanations">',
                        '<li data-type="{accessResult}"><i class="icon {[this.computeGlyph(values.accessResult)]}"></i><span data-qtip="{accessControllerId}">{explanation}</span></li>',
                    '</tpl>',
                '</ul>',
            '<tpl else>',
                '<p>-</p>',
            '</tpl>',
            {
                setAnyUserMode(mode)
                {
                    this._anyUser = mode == "anyUser";
                },
                
                computeGlyph: function(result)
                {
                    switch (result) 
                    {
                        case Ametys.plugins.coreui.rights.AccessResult.ANONYMOUS_ALLOWED:
                        case Ametys.plugins.coreui.rights.AccessResult.ANY_CONNECTED_ALLOWED:
                        case Ametys.plugins.coreui.rights.AccessResult.GROUP_ALLOWED:
                        case Ametys.plugins.coreui.rights.AccessResult.USER_ALLOWED:
                            return "ametysicon-check-1 allowed";
                        case Ametys.plugins.coreui.rights.AccessResult.ANONYMOUS_DENIED:
                        case Ametys.plugins.coreui.rights.AccessResult.ANY_CONNECTED_DENIED:
                        case Ametys.plugins.coreui.rights.AccessResult.GROUP_DENIED:
                        case Ametys.plugins.coreui.rights.AccessResult.USER_DENIED:
                            return "ametysicon-cross-1 denied";
                        case Ametys.plugins.coreui.rights.AccessResult.UNKNOWN:
                        default:
                            return "ametysicon-sign-question unknown";
                    }
                },
                
                computeSummaryLabel: function(result)
                {
                    switch (result) 
                    {
                        case Ametys.plugins.coreui.rights.AccessResult.ANONYMOUS_ALLOWED:
                        case Ametys.plugins.coreui.rights.AccessResult.ANY_CONNECTED_ALLOWED:
                        case Ametys.plugins.coreui.rights.AccessResult.GROUP_ALLOWED:
                        case Ametys.plugins.coreui.rights.AccessResult.USER_ALLOWED:
                            return this._anyUser ? "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_SUMMARY_ANY_USER_ALLOWED}}" : "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_SUMMARY_CURRENT_USER_ALLOWED}}";
                        case Ametys.plugins.coreui.rights.AccessResult.ANONYMOUS_DENIED:
                        case Ametys.plugins.coreui.rights.AccessResult.ANY_CONNECTED_DENIED:
                        case Ametys.plugins.coreui.rights.AccessResult.GROUP_DENIED:
                        case Ametys.plugins.coreui.rights.AccessResult.USER_DENIED:
                        case Ametys.plugins.coreui.rights.AccessResult.UNKNOWN:
                        default:
                            return this._anyUser ? "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_SUMMARY_ANY_USER_DENIED}}" : "{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_SUMMARY_CURRENT_USER_DENIED}}";
                    }
                }
            }
        );
        
        this._contextTpl = new Ext.XTemplate("...");
    },
    
    createPanel: function()
    {
        var me = this;
        
        // content will be filled with refresh
        this._contextCmp = Ext.create('Ext.Component', {ui: 'tool-hintmessage', flex: 1});
        
        // content will be filled with refresh
        this._resultCmp = Ext.create('Ext.panel.Panel', {
            anchor: "100%",
            cls: 'results',
            dockedItems: [{
	            layout: { 
	                type: 'hbox',
	                align: 'middle'
	            },
	            defaultType: 'button',
                margin: 0,
                items: [
                    {
                        xtype: 'component',
                        html: '<h2>{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RESULT_SUMMARY_LABEL}}</h2>',
                        flex: 1
                    },
                    {
                        // show/hide empty data
                        iconCls: this.showUnknowResultIconCls,
                        tooltip: this.showUnknowResultTooltip,
                        scope: this,
                        enableToggle: true,
                        toggleHandler: this.showUnknownResults,
                        cls: 'a-btn-light'
                    }
                ]
            }],
            tpl: this._resultTpl
        });
        
        return Ext.create('Ext.container.Container', {
            layout: {
                type: 'card'
            },
            cls: 'uitool-explain-user-right',
            items: [
                {
                    itemId: 'invalid-selection-card',
                    xtype: 'component',
                    cls: 'a-panel-text-empty',
                    border: false,
                    html: ''
                }, {
                    itemId: 'result-card',
                    cls: 'result-card-panel',
                    layout: "anchor",
                    defaults: {
                        anchor: "100%",
                        minWidth: 300,
                    },
                    scrollable: true,
                    dockedItems: [
                        this._contextCmp
                    ],
                    items: [
                        Ext.create("Ametys.form.field.RightByProfile", {
                            itemId: 'right',
                            fieldLabel: '{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RIGHT_WIDGET_LABEL}}',
                            labelAlign: 'top',
                            labelSeparator: '',
                            showProfilesIncludingRight: true,
                            value: Ametys.form.widget.Right.READER_RIGHT,
                            ametysDescription: '{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_RIGHT_WIDGET_DESC}}',
                            cls: 'ametys',
                            padding: "5 5 0 5",
                            allowBlank: false,
                            listeners: {change: function() {me.showOutOfDate();}}
                        }), {
                            xtype: 'edition.user',
                            itemId: 'user',
                            fieldLabel: '{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_USER_WIDGET_LABEL}}',
                            labelAlign: 'top',
                            labelSeparator: '',
                            cls: 'ametys',
                            padding: "5 5 0 5",
                            value: "CURRENT",
                            multiple: false,
                            emptyText: `{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_USER_WIDGET_EMPTY}}`,
                            ametysDescription: `{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_USER_WIDGET_DESC}}`,
                            listeners: {change: function() {me.showOutOfDate();}}
                        }, 
                        this._resultCmp
                    ]
                }
            ]
        });
    },
    
    setParams: function(params)
    {
        this._switchMode(params.mode || "anyUser")
        
        this.callParent(arguments);
    },
    
    showUnknownResults: function(btn, pressed)
    {
        if (pressed)
        {
            btn.setIconCls(this.hideUnknowResultIconCls);
            btn.setTooltip(this.hideUnknowResultTooltip);
            this._resultCmp.addCls('show-unknown')
        }
        else
        {
            btn.setIconCls(this.showUnknowResultIconCls);
            btn.setTooltip(this.showUnknowResultTooltip);
            this._resultCmp.removeCls('show-unknown')
        }
        this._resultCmp.hide();
        this._resultCmp.show();
    },
    
    _switchMode: function(mode)
    {
        if(this._mode != mode)
        {
            this._mode = mode;
            var contextHint;
            if (mode == 'anyUser')
            {
                this.getContentPanel().getComponent('result-card').getComponent('user').setVisible(true);
                
                contextHint = `{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_CONTEXT_HEADER_ANY_USER}}`
            }
            else
            {
                this.getContentPanel().getComponent('result-card').getComponent('user').setVisible(false);
                
                contextHint = `{{i18n PLUGINS_CORE_UI_RIGHTS_EXPLAIN_TOOL_CONTEXT_HEADER_CURRENT_USER}}`
            }
            
            contextHint += `</br><tpl if="contextType">({contextType})</tpl> <strong data-qtip="{contextId}">{[Ext.String.escapeHtml(values.contextLabel)]}</strong>`
            this._contextTpl.set(contextHint, true);
        }
    },
    
    setNoSelectionMatchState: function (message)
    {
        var mainPanel = this.getContentPanel()
        mainPanel.setActiveItem('invalid-selection-card');
        mainPanel.getComponent('invalid-selection-card').setHtml(message);
        // call parent to ensure normal operation
        this.callParent(arguments);
    },
    
    refresh: function(manual)
    {
        this.showRefreshing();
        
        var targets = this.getCurrentSelectionTargets(); // [][0] == undefined
        
        if (targets.length > 1
            || targets.length == 0 && Ametys.message.MessageBus.getCurrentSelectionMessage().getTargets().length != 0)
        {
            // if selection multiple or not empty, do nothing
            this.showUpToDate(true);
            return;
        }
        
        var target = targets[0];
        
        this.getContentPanel().setActiveItem('result-card');
        
        // Update context header
        var contextId = this.getContextId(target);
        var contextInfo = this.getContextInfo(target);
        this._contextCmp.setHtml(this._contextTpl.apply({contextLabel: contextInfo.label, contextId: contextId, contextType: contextInfo.type}));

        // Check if right is set. If so call server. Otherwise stop and hide the result component
        var right = this.getContentPanel().getComponent('result-card').getComponent('right').getValue();
        if (right != null)
        {
            this._resultCmp.setVisible(true);
            this._updateResultCard(contextId, right);
        }
        else
        {
            this._resultCmp.setVisible(false);
            
            this.showUpToDate();
        }
    },
    
    _updateResultCard: function(context, right)
    {
        var serverId = this.getConvertorId();
        
        var args = {
            context: context
        };
        
        if (this._mode == "anyUser")
        {
            var user = this.getContentPanel().getComponent('result-card').getComponent('user').getValue();
            args.user = user;
            this.serverCall('explainRight', [right, user, context, serverId], this._explainRightCb, {arguments: args, cancelCode: this.getId() + "$explain"});
        }
        else
        {
            this.serverCall('explainCurrentUserRight',[right, context, serverId], this._explainRightCb, {arguments: args, cancelCode: this.getId() + "$explain"})
        }
    },
    
    _explainRightCb: function(response, args)
    {
        var result = response.result != Ametys.plugins.coreui.rights.AccessResult.UNKNOWN ? response.result : Ametys.plugins.coreui.rights.AccessResult.USER_DENIED
        this._resultCmp.update({
                result : result,
                explanations: response.explanations,
                user: args.user,
                mode: this._mode
            });
        this.showUpToDate();
    }
   });