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

/**
 * <p>This tool displays a tree of statistics
 * @private
 */
Ext.define('Ametys.plugins.admin.jvmstatus.StatisticsTool', {
    extend: 'Ametys.tool.Tool',
    
    /**
     * @private
     * @property {Ext.tree.Panel} _tree The statistics tree
     */
    
    getMBSelectionInteraction: function() 
    {
        return Ametys.tool.Tool.MB_TYPE_NOSELECTION;
    },
    
    createPanel: function ()
    {
        this._tree = this._createStatisticsTreePanel();
        return this._tree;
    },
    
    /**
     * Get the tree of the tool
     * @return {Ext.tree.Panel} The main tree component of the tool
     */
    getTree: function()
    {
        return this._tree;
    },
    
    setParams: function (params)
    {
        this.callParent(arguments);
        this.showOutOfDate();
    },
    
    refresh: function ()
    {        
        this.showRefreshing("{{i18n PLUGINS_ADMIN_STATISTICS_TOOL_LOADING}}");
        this._tree.getStore().load({node: this._tree.getRootNode(), callback:  Ext.bind(function() { this.showRefreshed(); this._tree.getRootNode().expand(); }, this)});
    },
    
    /**
     * @private
     * Draw the tree panel for the statistics
     */
    _createStatisticsTreePanel: function()
    {
        function renderer(value)
        {
            if (value === null) return '';
            if (Ext.isArray(value)) return value.map(renderer).join(', ');
            if (Ext.isNumber(value)) return value.toLocaleString();
            if (Ext.isBoolean(value)) return '<span class="a-grid-glyph ' + (value === true ? "ametysicon-check34" : "ametysicon-sign-raw-cross") + '" title="' + value + '"></span>';
            return "\"" + value + "\"";
        }
        
        return Ext.create('Ext.tree.Panel', {
            
            cls:'statistics-tree',
            border: false,
            scrollable: true,
            
            rootVisible: false,
            
            columns: [{
                xtype: 'treecolumn',
                text: "{{i18n PLUGINS_ADMIN_STATISTICS_TOOL_COL_NAME}}",
                dataIndex: 'label',
                width: 300,
                sortable: true
            }, {
                text: "{{i18n PLUGINS_ADMIN_STATISTICS_TOOL_COL_VALUE}}",
                dataIndex: 'value',
                flex: 1,
                sortable: true,
                renderer: renderer
            }],
            
            // Filter box
            dockedItems: [{
                dock: 'top',
                xtype: 'toolbar',
                layout: {
                    type: 'hbox',
                    align: 'stretch'
                },
                
                border: false,
                defaults : {
                    cls: 'ametys',
                    labelWidth: 55,
                    labelSeparator: ''
                },
                
                items: [{
                    // Search input
                    xtype: 'textfield',
                    itemId: 'search-filter-input',
                    cls: 'ametys',
                    flex: 1,
                    maxWidth: 300,
                    emptyText: "{{i18n PLUGINS_ADMIN_STATISTICS_TOOL_FILTER_EMPTYTEXT}}",
                    enableKeyEvents: true,
                    msgTarget: 'qtip',
                    listeners: {change: Ext.Function.createBuffered(this._filterByTitle, 300, this)}
                }, {
                    // Clear filter
                    tooltip: "{{i18n PLUGINS_ADMIN_STATISTICS_TOOL_FILTER_CLEAR}}",
                    handler: Ext.bind (this._clearFilter, this),
                    iconCls: 'a-btn-glyph ametysicon-eraser11 size-16',
                    cls: 'a-btn-light'
                }]
            }],
            
            store: Ext.create('Ext.data.TreeStore', {
                root: {
                    text: 'root',
                    type: 'root',
                    id: 'root',
                    expanded: false
                },  
                
                autoLoad: false,
                
                proxy: {
                    type: 'ametys',
                    role: 'org.ametys.runtime.plugins.admin.statistics.StatisticsProviderExtensionPoint',
                    methodName: 'getStatisticsTree',
                    methodArguments: [],
                    reader: {
                        type: 'json',
                        rootProperty: 'children'
                    }
                },
                
                sorters: [ { property: 'title', direction: "ASC" }]
                
            })
        });
    },
    
    /**
     * @private
     * Filters queries by input field value.
     * @param {Ext.form.Field} field The field
     */
    _filterByTitle: function (field)
    {
        var currentSelection = this.getContentPanel().getSelection();
        
        var value = Ext.String.trim(field.getValue());
        
        this.getContentPanel().getStore().clearFilter();
        
        if (value)
        {
            this._regexFilter = new RegExp(value, 'i');
            
            this.getContentPanel().getStore().filterBy(Ext.bind(this._filterByTextAndChildren, this));
        }
        
        if (currentSelection.length > 0)
        {
            var me = this;
            Ext.Array.each(currentSelection, function (sel) {
                if (me.getContentPanel().getStore().findExact(me.getContentPanel().getStore().getModel().idProperty, sel.getId()) == -1)
                {
                    // The current selection is not visible, clear the selection
                    me.getContentPanel().getSelectionModel().deselect([sel]);
                }
            });
            
            var selection = this.getContentPanel().getSelection();
            if (selection.length > 0)
            {
                this.getContentPanel().ensureVisible(selection[0].getPath());
            }
        }
    },
    
        /**
     * @private
     * Filter function that check if a node in the tree should be visible or not.
     * @param {Ext.data.Model} record The record to check.
     * @return {boolean} True if the record should be visible.
     */
    _filterByTextAndChildren: function (record)
    {
        var isVisible = this._regexFilter == null || this._regexFilter.test(record.data.label);
        if (!isVisible)
        {
            // if the record does not match, we check if any child is visible. If at least one is, this record should not be hidden.
            // This is efficient because the data is in the store, and is not loaded in the view.
            for (var i = 0; !isVisible && i < record.childNodes.length; i++) {
                isVisible = this._filterByTextAndChildren(record.childNodes[i]);
            }
        }
        
        if (isVisible)
        {
            this.getContentPanel().expandNode(record);
        }
        
        return isVisible; 
    },  
    
    /**
     * Clear the current filter
     */
    _clearFilter: function()
    {
        this.getContentPanel().down("#search-filter-input").reset();
    }
});