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

/**
 * Class defining the pilotage dashboard tool
 */
Ext.define('Ametys.plugins.odf.pilotage.tool.PilotageDashboardTool', {
    extend: "Ametys.tool.Tool",
    
    /**
     * @property {String} _catalog
     * @private
     */
     
     /**
     * @property {String} _orgUnit
     * @private
     */
     
     /**
     * @property {Boolean} _isRulesEnabled
     * @private
     */
    
    statics: {
        /**
         * @static
         * Open the program search tool
         * @param {String} catalog The catalog
         * @param {String[]} orgUnit The orgUnit
         * @param {String} pilotageStatus The pilotage status
         */
        openProgramSearchTool: function(catalog, orgUnit, pilotageStatus)
        {
            var params = {
                startSearchAtOpening: true,
                values: {
                    "reference-orgUnit-eq": orgUnit && orgUnit.trim() != "" ? [orgUnit] : [],
                    "reference-catalog-eq": catalog,
                    "reference-mccPilotageStatus-eq": pilotageStatus
                },
                "id": "search-ui.program-pilotage"
            };
            
            Ametys.tool.ToolsManager.openTool('uitool-odf-education', params);
        },
        
        /**
         * @static
         * Open the container search tool
         * @param {String} catalog The catalog
         * @param {String} yearId The year id
         * @param {String[]} orgUnit The orgUnit
         * @param {String} thematicId The thematic id
         * @param {String} mccStatus The MCC status
         * @param {String} invalidData true to get invalid data
         */
        openContainerSearchTool: function(catalog, yearId, orgUnit, thematicId, mccStatus, invalidData)
        {
            var values = {
                "reference-parentOrgunits-eq": orgUnit && orgUnit.trim() != "" ? [orgUnit] : [],
                "reference-catalog-eq": catalog,
                "reference-overridenThematics-eq": thematicId,
                "reference-nature-eq": yearId,
                "reference-mccWorkflowStatus-eq": mccStatus  && mccStatus.trim() != "" ? [mccStatus] : []
            }
            
            if (invalidData)
            {
                values["reference-invalidData-eq"] = true
            }
            
            var params = {
                startSearchAtOpening: true,
                values: values,
                "id": "search-ui.container-pilotage"
            };
            
            Ametys.tool.ToolsManager.openTool('uitool-odf-container-search', params);
        },
    },
    
    createPanel: function()
    {
        this._panel = Ext.create('Ext.Panel', { 
            cls: 'pilotage-dashboard-tool',
            dockedItems: this._getTopPanel(),
            scrollable: true,
            items: [
                {
                    xtype: 'container',
                    layout: {
                        type: 'hbox',
                        align: 'stretch'
                    },
                    items: [
                        this._getPilotageMCCWorkflowStatsPanel(),
                        {
                            xtype: 'tbspacer',
                            flex: 0.01
                        },
                        this._getPilotageWorkflowStatsPanel()
                    ]
                },
                this._getPilotageRulesStatsPanel()
            ]
        });
        
        return this._panel;            
    },
    
    /**
     * @private
     * Get the top panel for filters
     * @return {Ext.Panel} the top panel
     */
    _getTopPanel: function ()
    {
        let store = Ext.create('Ext.data.Store', {
            autoLoad: true,
            
            proxy: {
                type: 'ametys',
                role: 'org.ametys.plugins.odfpilotage.dashboard.PilotageDashboardHelper',
                methodName: 'getOrgUnits',
                reader: {
                    type: 'json',
                    rootProperty: 'orgUnits'
                }
            },
            
            listeners: {
                load: {
                    fn: function(store, values)
                    {
                        if (values.length > 0)
                        {
                            this._panel.down("#orgUnits").setValue(values[0].id)
                        }
                    },
                    scope: this
                }
            },
            
            fields: [
                {name: 'id', mapping: 'id'},
                {name: 'label', mapping: 'label'}
            ],
            
            sorters: [
                {property: 'label', direction:'ASC'}
            ]
        });
        
        return Ext.create({
            dock: 'top',
            xtype: 'container',
            layout: {
                type: 'hbox',
            },
            cls: 'top',
            items: [
                
                Ametys.odf.catalog.CatalogDAO.createComboBox({
                    name: 'catalog',
                    labelWidth: 60,
                    fieldLabel: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_FILTER_CATALOG_LABEL}}",
                    itemId: 'catalog',
                    allowBlank: false,
                    cls: 'ametys catalogs',
                    listeners: {
                        change: {
                            fn: function(select) {
                                this._catalog = select.value;
                                this.refresh();
                            }, 
                            scope: this
                        }
                    }
                }),
                Ext.create('Ext.form.field.ComboBox', {
                    cls: 'ametys orgunits',
                    labelWidth: 74,
                    forceSelection: true,
                    editable: false,
                    triggerAction: 'all',
                    width: 450,
                    queryMode: 'local',
                    fieldLabel: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_FILTER_ORGUNITS_LABEL}}",
                    name: 'orgUnits',
                    itemId: 'orgUnits',
                    store: store,
                    listeners: {
                        change: {
                            fn: function(select) {
                                this._orgUnit = select.getValue();
                                this.refresh();
                            }, 
                            scope: this
                        }
                    },
                    valueField: 'id',
                    displayField: 'label',
                })
            ]
        });
    },
    
    /**
     * @private
     * Get the rules stats panel
     * @return {Ext.Panel} the rules stats panel
     */
    _getPilotageRulesStatsPanel: function()
    {
        this._rulesStatsStore = Ext.create('Ext.data.Store', {
            proxy: {
                type: 'ametys',
                role: 'org.ametys.plugins.odfpilotage.dashboard.PilotageDashboardHelper',
                methodName: 'getRulesStats',
                methodArguments: ['catalog', 'orgUnit'],
                reader: {
                    type: 'json'
                }
            },
            fields: [
                {name: 'thematic', convert: Ext.bind(Ametys.plugins.cms.search.SearchGridHelper.convertContent, null, ['thematic'], true)},
                {name: 'thematicTitle'},
                {name: 'regime'},
                {name: 'nbSessions'},
                {name: 'pourcent'},
                {name: 'number'},
                {name: 'total'},
                {name: 'hasRight'}
            ],
            
            listeners: {
                beforeload: {fn: this._onPilotageStatsStoreBeforeLoad, scope: this}
            }
        });
        
        this._rulesStatsGrid = Ext.create('Ext.grid.Panel',{
            title : "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_RULES_STATS_PANEL_TITLE}}",
            cls: 'rules-stats-panel',
            scrollable: true,
            maxHeight: 280,
            minHeight: 280,
            hidden: true,
            
            store : this._rulesStatsStore,
            columns: [
                {header: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_RULES_STATS_PANEL_THEMATIC_COLUMN_LABEL}}", menuDisabled : true, sortable: false, flex: 1, renderer: Ext.bind(this._renderThematic, this), dataIndex: 'thematic'},
                {header: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_RULES_STATS_PANEL_REGIMES_COLUMN_LABEL}}", menuDisabled : true, sortable: false, flex: 1, dataIndex: 'regime', renderer: Ext.bind(this._renderRegime, this)},
                {header: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_RULES_STATS_PANEL_NUMBER_OF_SESSIONS_COLUMN_LABEL}}", menuDisabled : true, sortable: false, flex: 1, dataIndex: 'nbSessions', renderer: Ext.bind(this._renderNbSessions, this)},
                {header: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_RULES_STATS_PANEL_NUMBER_COLUMN_LABEL}}", menuDisabled : true, sortable: false, width: 300, dataIndex: 'number', renderer: Ext.bind(this._renderNbContainers, this)},
            ]
        });
        
        return this._rulesStatsGrid;
    },
    
    /**
     * @private
     * Get the pilotage workflow stats panel
     * @return {Ext.Panel} the pilotage workflow stats panel
     */
    _getPilotageWorkflowStatsPanel: function ()
    {
        this._pilotageWorkflowStatsStore = Ext.create('Ext.data.Store', {
            proxy: {
                type: 'ametys',
                role: 'org.ametys.plugins.odfpilotage.dashboard.PilotageDashboardHelper',
                methodName: 'getPilotageWorkflowStats',
                methodArguments: ['catalog', 'orgUnit'],
                reader: {
                    type: 'json'
                }
            },
            fields: [
                {name: 'label'},
                {name: 'number'},
                {name: 'pourcent'},
                {name: 'status'},
                {name: 'total'},
                {name: 'type'},
                {name: 'attributName'}
            ],
            groupField: 'type',
            
            listeners: {
                beforeload: {fn: this._onPilotageStatsStoreBeforeLoad, scope: this}
            }
        });
        
        this._pilotageWorkflowStatsGrid = Ext.create('Ext.grid.Panel',{
            title : "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_WORKFLOW_STATS_PANEL_TITLE}}",
            flex: 1, 
            minHeight: 280,
            
            store : this._pilotageWorkflowStatsStore,
            columns: [
                {header: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_WORKFLOW_STATS_PANEL_LABEL_COLUMN_LABEL}}", menuDisabled : true, sortable: false, flex: 1, dataIndex: 'label', renderer: Ext.bind(this._renderProgramLabel, this)},
                {header: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_WORKFLOW_STATS_PANEL_NUMBER_COLUMN_LABEL}}", menuDisabled : true, sortable: false, width: 300, dataIndex: 'number', renderer: Ext.bind(this._renderNbPrograms, this)}
            ],
            
            // Grouping by type
            features: [
                {
                    ftype: 'grouping',
                    enableGroupingMenu: false,
                    groupHeaderTpl: [
                        '{name:this.typeLabel}',
                        {
                            typeLabel: function() {
                                return "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_WORKFLOW_STATS_PANEL_GROUP_PROGRAM}}";
                            }
                        }
                    ]
                } 
            ]
        });
        
        return this._pilotageWorkflowStatsGrid;
    },
    
    /**
     * @private
     * Get the pilotage MCC workflow stats panel
     * @return {Ext.Panel} the pilotage MCC workflow stats panel
     */
    _getPilotageMCCWorkflowStatsPanel: function ()
    {
        this._pilotageMCCWorkflowStatsStore = Ext.create('Ext.data.Store', {
            proxy: {
                type: 'ametys',
                role: 'org.ametys.plugins.odfpilotage.dashboard.PilotageDashboardHelper',
                methodName: 'getPilotageMCCWorkflowStats',
                methodArguments: ['catalog', 'orgUnit'],
                reader: {
                    type: 'json'
                }
            },
            fields: [
                {name: 'label'},
                {name: 'number'},
                {name: 'pourcent'},
                {name: 'status'},
                {name: 'total'},
                {name: 'type'},
                {name: 'attributName'}
            ],
            groupField: 'type',
            
            listeners: {
                beforeload: {fn: this._onPilotageStatsStoreBeforeLoad, scope: this}
            }
        });
        
        this._pilotageMCCWorkflowStatsGrid = Ext.create('Ext.grid.Panel',{
            title : "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_MCC_WORKFLOW_STATS_PANEL_TITLE}}",
            flex: 1, 
            minHeight: 280,
            
            store : this._pilotageMCCWorkflowStatsStore,
            columns: [
                {header: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_MCC_WORKFLOW_STATS_PANEL_LABEL_COLUMN_LABEL}}", menuDisabled : true, sortable: false, flex: 1, dataIndex: 'label', renderer: Ext.bind(this._renderContainerLabel, this)},
                {header: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_MCC_WORKFLOW_STATS_PANEL_NUMBER_COLUMN_LABEL}}", menuDisabled : true, sortable: false, width: 300, dataIndex: 'number', renderer: Ext.bind(this._renderNbContainers, this)}
            ],
            
            // Grouping by type
            features: [
                {
                    ftype: 'grouping',
                    enableGroupingMenu: false,
                    groupHeaderTpl: [
                        '{name:this.typeLabel}',
                        {
                            typeLabel: function(name) {
                                switch (name) {
                                    case "program":
                                        return "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_MCC_WORKFLOW_STATS_PANEL_GROUP_PROGRAM}}";
                                    case "container":
                                    default:
                                        return "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_MCC_WORKFLOW_STATS_PANEL_GROUP_CONTAINER}}";
                                }
                            }
                        }
                    ]
                } 
            ]
        });
        
        return this._pilotageMCCWorkflowStatsGrid;
    },
    
     /**
     * Function to render a thematic content value
     * @param {Object} value The data value
     * @param {Object} metaData A collection of metadata about the current cell
     * @param {Ext.data.Model} record The record
     * @param {Number} rowIndex The index of the current row
     * @param {Number} colIndex The index of the current column
     * @param {Ext.data.Store} store The store
     * @param {Ext.view.View} view The current view
     */
    _renderThematic: function (value, metaData, record, rowIndex, colIndex, store, view)
    {
        return record.data.hasRight
            ? Ametys.plugins.cms.search.SearchGridHelper.renderContent(value, metaData, record, rowIndex, colIndex, store, view, 'thematic')
            : record.data.thematicTitle;
    },
    
    /**
     * @private
     * Render the pilotage number of programs
     * @param {Object} value The data value
     * @param {Object} metaData A collection of metadata about the current cell
     * @param {Ext.data.Model} record The record
     * @return {String} the render
     */
    _renderNbPrograms: function(value, metaData, record)
    {
        let number = record.data.number;
        let tooltip = number > 1 
            ? Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_WORKFLOW_STATS_NB_PROGRAM_SEVERAL_TOOLTIP}}", record.data.number, record.data.total)
            : Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_WORKFLOW_STATS_NB_PROGRAM_ONE_TOOLTIP}}", record.data.number, record.data.total);
        return "<a title=\"" + tooltip + "\" href='javascript:void(0)' onclick='Ametys.plugins.odf.pilotage.tool.PilotageDashboardTool.openProgramSearchTool(\"" + this._catalog + "\", \"" + this._orgUnit + "\", \"" + record.data.status + "\")'>" + value + "</a> (" + record.data.pourcent + " %)";
    },
    
    /**
     * @private
     * Render the pilotage number of containers
     * @param {Object} value The data value
     * @param {Object} metaData A collection of metadata about the current cell
     * @param {Ext.data.Model} record The record
     * @return {String} the render
     */
    _renderNbContainers: function(value, metaData, record)
    {
        let number = record.data.number;
        let tooltip = number > 1 
            ? Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_RULES_STATS_NB_CONTAINER_SEVERAL_TOOLTIP}}", record.data.number, record.data.total)
            : Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_RULES_STATS_NB_CONTAINER_ONE_TOOLTIP}}", record.data.number, record.data.total);
        return record.data.thematic
            ? "<a title=\"" + tooltip + "\" href='javascript:void(0)' onclick='Ametys.plugins.odf.pilotage.tool.PilotageDashboardTool.openContainerSearchTool(\"" + this._catalog + "\", \"" + this._yearId + "\", \"" + this._orgUnit + "\", \"" + record.data.thematic + "\")'>" + value + "</a> (" + record.data.pourcent + " %)"
            : record.data.attributName == 'invalidData'
                ? "<a title=\"" + tooltip + "\" href='javascript:void(0)' onclick='Ametys.plugins.odf.pilotage.tool.PilotageDashboardTool.openContainerSearchTool(\"" + this._catalog + "\", \"" + this._yearId + "\", \"" + this._orgUnit + "\", null, \"" + record.data.status + "\", true)'>" + value + "</a> (" + record.data.pourcent + " %)"
                : "<a title=\"" + tooltip + "\" href='javascript:void(0)' onclick='Ametys.plugins.odf.pilotage.tool.PilotageDashboardTool.openContainerSearchTool(\"" + this._catalog + "\", \"" + this._yearId + "\", \"" + this._orgUnit + "\", null, \"" + record.data.status + "\", false)'>" + value + "</a> (" + record.data.pourcent + " %)";
    },
    
    /**
     * @private
     * Render the label for container workflow status
     * @param {Object} value The data value
     * @param {Object} metaData A collection of metadata about the current cell
     * @param {Ext.data.Model} record The record
     * @return {String} the render
     */
    _renderContainerLabel: function(value, metaData, record)
    {
        let invalidDataTooltip = Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_WORKFLOW_STATS_CONTAINERS_INVALID_DATA_TOOLTIP}}");
        let noValidationTooltip = Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_WORKFLOW_STATS_CONTAINERS_NO_VALIDATION_TOOLTIP}}");
                
        return record.data.attributName == 'invalidData'
            ? "<span title=\"" + invalidDataTooltip + "\">" + value + "<span>"
                : record.data.status == "NONE"
                     ? "<span title=\"" + noValidationTooltip + "\">" + value + "<span>"
                     : value;
    },
    
    /**
     * @private
     * Render the label for program workflow status
     * @param {Object} value The data value
     * @param {Object} metaData A collection of metadata about the current cell
     * @param {Ext.data.Model} record The record
     * @return {String} the render
     */
    _renderProgramLabel: function(value, metaData, record)
    {
        let noValidationTooltip = Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_WORKFLOW_STATS_PROGRAMS_NO_VALIDATION_TOOLTIP}}");
                
        return record.data.status == "NONE"
            ? "<span title=\"" + noValidationTooltip + "\">" + value + "<span>"
            : value;
    },
    
    /**
     * @private
     * Render the regime
     * @param {Object} value The data value
     * @param {Object} metaData A collection of metadata about the current cell
     * @param {Ext.data.Model} record The record
     * @return {String} the renderer of regime
     */
    _renderRegime: function(value, grid, record)
    {
        if (value)
        {
            return value;
        }
        
        return "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_RULES_STATS_ALL_REGIME}}";
    },
    
    /**
     * @private
     * Render the number of sessions
     * @param {Object} value The data value
     * @param {Object} metaData A collection of metadata about the current cell
     * @param {Ext.data.Model} record The record
     * @return {String} the renderer of the number of sessions
     */
    _renderNbSessions: function(value, grid, record)
    {
        if (value)
        {
            return value;
        }
        
        return "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_RULES_STATS_ALL_NB_SESSION}}";
    },
    
    /**
     * Set the filter parameters before loading the store.
     * @param {Ext.data.Store} store The store.
     * @param {Ext.data.operation.Operation} operation The Ext.data.Operation object that will be passed to the Proxy to load the Store.
     * @private
     */
    _onPilotageStatsStoreBeforeLoad: function(store, operation)
    {
        var params = operation.getParams() || {};
        operation.setParams(Ext.apply(params, {
            catalog: this._catalog,
            orgUnit: this._orgUnit
        }));
    },
    
    refresh: function()
    {
        this.callParent(arguments);
        
        if (this._isRulesEnabled === undefined || this._yearId === undefined)
        {
            Ametys.data.ServerComm.callMethod({
                role: "org.ametys.plugins.odfpilotage.dashboard.PilotageDashboardHelper",
                methodName: "getDashboardInfo",
                parameters: [],
                callback: {
                    handler: this._getDashboardInfoCB,
                    scope: this
                },
                waitMessage: {
                    target: this.getContentPanel()
                }
            });
        }
        else
        {
            this._refreshCB(this._isRulesEnabled);
        }
    },

    /**
     * Get dashboard information callback
     * @param {Object} results the results
     * @private
     */
    _getDashboardInfoCB: function(results)
    {
        if (results.error)
        {
            Ametys.Msg.show({
                title: "{{i18n PLUGINS_ODF_PILOTAGE_DASHBOARD_NO_YEAR_ERROR}}",
                msg: "{{i18n PLUGINS_ODF_PILOTAGE_DASHBOARD_NO_YEAR_MSG}}",
                buttons: Ext.Msg.OK,
                icon: Ext.Msg.ERROR
            });
        }
        else
        {
            this._isRulesEnabled = results.isRulesEnabled;
            this._yearId = results.yearId;
            this._refreshCB(this._isRulesEnabled);
        }
    },
    
    /**
     * Refresh callback
     * @param {Boolean} isRulesEnabled true is rules are enabled
     * @private
     */
    _refreshCB: function(isRulesEnabled)
    {
        if (this._catalog)
        {
            this._reloadStores(isRulesEnabled);
        }
        else
        {
            Ametys.odf.catalog.CatalogDAO.getDefaultCatalogName(
                [],
                function(catalogName) {
                    this._panel.down("#catalog").setValue(catalogName);
                },
                { scope: this }
            );
        }
    },
    
    /**
     * Reload all the store
     * @param {Boolean} isRulesEnabled true is rules are enabled
     * @private
     */
    _reloadStores: function(isRulesEnabled)
    {
        if (isRulesEnabled)
        {
            this._rulesStatsGrid.show();
            this._rulesStatsStore.load({
                callback: Ext.bind(function() {
                    if (this._rulesStatsStore.getCount() > 0)
                    {
                        this._rulesStatsGrid.getView().unmask();
                    }
                    else
                    {
                        this._rulesStatsGrid.getView().mask("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DASHBOARD_RULES_STATS_PANEL_NO_RESULT}}", 'ametys-mask-unloading');
                    }
                }, this)
            });
        }
        
        this._pilotageWorkflowStatsStore.load();
        this._pilotageMCCWorkflowStatsStore.load();
    },
    
    getMBSelectionInteraction: function()
    {
        return Ametys.tool.Tool.MB_TYPE_NOSELECTION;
    },
});