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


/**
 * Show the values of a repeater in a dialog, and allow the inline modification of its entries
 */
Ext.define('Ametys.plugins.odfpilotage.widget.DoubleMCCSearchGridRepeater', {
    singleton: true,
    
    showRepeaterDialog: function()
    {
        return Ametys.plugins.cms.search.SearchGridRepeaterDialog.showRepeaterDialog.apply(this, arguments);
    },
    
    _getEducationalPath: function(parentRecord, dataIndex)
    {
        let data = parentRecord.get(dataIndex[0] + "_repeater")._educationalPath;
        return data ? data[parentRecord.getId()] : null;
    },
    
    _openDialog: function (title, parentRecord, contentId, subcolumns, repeaterCfg, dataIndex, metadataPath, contentGridId, callback)
    {
        let me = this;
        
        let items = [];
        let grids = [];
        
        let educationalPath = this._getEducationalPath(parentRecord, dataIndex);
        let educationalPathLabel = parentRecord.get(dataIndex[0] + "_repeater")._educationalPathLabel[parentRecord.getId()];
        
        let rootsLabels = "";
        let roots = (parentRecord.get(dataIndex[0] + "_repeater")._educationalPathRootLabels || {})[parentRecord.getId()];
        if (roots)
        {
            rootsLabels = "<br/><br/>{{i18n PLUGINS_ODF_PILOTAGE_RIGHTS_MCCCOURSE_MCCSESSIONS_EDUCATIONAL_PATH_MULTIPLE_GLOBAL_INTRO}}<ul style='margin-top: 0;'>" + roots.map(x => "<li><strong>" + x + "</strong></li>").join("") + "</ul>{{i18n PLUGINS_ODF_PILOTAGE_RIGHTS_MCCCOURSE_MCCSESSIONS_EDUCATIONAL_PATH_MULTIPLE_GLOBAL_WARN}}";
            
            // Hide the common column
            for (let subcolumn of subcolumns)
            {
                for (let c of subcolumn)
                {
                    if (c.name == "common")
                    {
                        c.hidden = true;
                    }
                }
            }
        }
        else
        {
            // Ensure visibility of common column
            for (let subcolumn of subcolumns)
            {
                for (let c of subcolumn)
                {
                    if (c.name == "common")
                    {
                        c.hidden = false;
                    }
                }
            }
        }
        
        this._cannotEditCommon = {};
        for (let i = 0; i < metadataPath.length; i++)
        {
            this._cannotEditCommon[i] = this._isRecordMetadataNotModifiable(parentRecord, metadataPath[i], "common", null, null);
        }

        items.push({
            xtype: "component",
            ui: 'tool-hintmessage',
            html: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DIALOG_MCCCOURSE_LABEL}} <strong>" + educationalPathLabel + "</strong>" + rootsLabels
        });
                
        this._eliminatedRecordsForEducationPath = [];
        
        for (let i = 0; i < subcolumns.length; i++)
        {
            let eliminated;
            function filter(repeater)
            {
                let condition = x => x.values.common !== false || x.values.path == educationalPath;
                
                eliminated = repeater.entries.filter(x => !condition(x))
                return repeater.entries.filter(condition)
            }
            
            let items1 = Ametys.plugins.cms.search.SearchGridRepeaterDialog._createItems(title, parentRecord, contentId, subcolumns[i], repeaterCfg[i], dataIndex[i], metadataPath[i], contentGridId, {add: Ext.bind(this._onAdd, this)}, filter, this);
            items1[0]._gridIndex = grids.length;
            grids.push(items1[0]);
            items.push({
                xtype: 'panel', 
                flex: 1,
                layout: 'fit',
                title: title[i],
                items: items1
            });
            
            this._eliminatedRecordsForEducationPath.push(eliminated); 
        }
        
        items.splice(2, 0, {
            xtype: 'container',
            layout: 'hbox',
            style: {
                marginTop: '20px'
            },
            items: [
                { xtype: 'tbspacer', flex: 1 },
                {
                    xtype: 'button',
                    text: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_MCCCOURSE_COPY_LABEL}}",
                    handler: Ext.bind(this._copySessions, this, [dataIndex[dataIndex.length - 1], false], 1),
                    tooltip: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_MCC_SESSIONS_COPY_TOOLTIP}}"
                },
                { xtype: 'tbspacer', flex: 1 }
            ]
        });
        
        // If the "common" column is not hidden
        // And if we are not in read only mode
        if (grids[0].getColumns().filter(x => x.dataIndex == 'common' && !x.hidden).length > 0)
        {
            items.push({
                xtype: 'component',
                style: {
                    marginTop: '5px',
                    textAlign: 'right'
                },
                html: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_MCC_SESSIONS_WARN_ORDER}}"
            });
        }

        var isGrid1ReadOnly = parentRecord.data['notEditableData'] === true || parentRecord.data['notEditableDataIndex'] && Ext.Array.contains(parentRecord.data['notEditableDataIndex'], metadataPath[0]);
        var isGrid2ReadOnly = parentRecord.data['notEditableData'] === true || parentRecord.data['notEditableDataIndex'] && Ext.Array.contains(parentRecord.data['notEditableDataIndex'], metadataPath[1]);
        var dialog = Ametys.plugins.cms.search.SearchGridRepeaterDialog._showDialog(
            "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_DIALOG_MCCCOURSE_LABEL}} " + parentRecord.get('title'), 
            items, 
            {type: 'vbox', align: 'stretch'},
            function () {
                Ametys.plugins.odfpilotage.widget.DoubleMCCSearchGridRepeater._ok(dialog, parentRecord, grids, dataIndex, contentId, callback);
            },
            callback,
            [
                {
                    text :"{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_MCC_SESSIONS_BUTTON_HANDLE}}",
                    handler: function() {
                        Ametys.plugins.odf.pilotage.helper.DoubleMCCTemplatesHelper.handleMCCSessionsTemplates(grids, parentRecord.get("mccRegime"), !(isGrid1ReadOnly || repeaterCfg[0].disabled), !(isGrid2ReadOnly || repeaterCfg[1].disabled));
                    },
                    tooltip: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_MCC_SESSIONS_HANDLE_TOOLTIP}}",
                    scope: this
                },
                {
                    text :"{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_MCC_SESSIONS_BUTTON_CREATE}}",
                    handler: function() {
                        Ametys.plugins.odf.pilotage.helper.DoubleMCCTemplatesHelper.createTemplate(grids);
                    },
                    tooltip: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_MCC_SESSIONS_CREATE_TOOLTIP}}",
                    itemId: 'create-user-session',
                    scope: this
                },
                { xtype: 'tbspacer', flex: 1 }
            ]
        );
        
        this._initCreateTemplateButton(dialog, grids);
        
        dialog.setReadOnly = function() {
            let copyButton = dialog.items.get(2); 
            copyButton.disable();
            copyButton._definitiveDisabled = true;
            for (let i = 1; i < dialog.items.getCount(); i+=2)
            {
                dialog.items.get(i).items.get(0).getStore().fireEvent('datachanged');
            }
            
            dialog.items.get(4).hide();
            
            if (dialog.items.get(3).items.get(0).getStore().getCount() == 0)
            {
                copyButton.hide();
                dialog.items.get(3).hide();
                dialog.setHeight(500);
            }
        }
        
        if (isGrid2ReadOnly || repeaterCfg[1].disabled)
        {
            dialog.setReadOnly();
        }
        
        enableDisableCopyButton();
        grids[0].getStore().on('datachanged', enableDisableCopyButton);
        
        return dialog;
        
        function enableDisableCopyButton()
        {
            let copyButton = dialog.items.get(2);
            if (copyButton._definitiveDisabled)
            {
                return;
            } 
            let nbItemsToCopy = me._copySessions(copyButton.down('button'), dataIndex[dataIndex.length - 1], true);
            copyButton.setDisabled(nbItemsToCopy == 0);
        }
    },
        
    _onAdd: function(repeaterRecord, grid)
    {
        if (this._cannotEditCommon[grid._gridIndex])
        {
            repeaterRecord.set('common', false);
        }
    },
    
    _initCreateTemplateButton: function(dialog, grids)
    {
        let storeGrid1 = grids[0].getStore();
        let storeGrid2 = grids[1].getStore();
        let createTemplateButton = dialog.down("#create-user-session");
        
        if (storeGrid1.getCount() == 0 && storeGrid2.getCount() == 0)
        {
            createTemplateButton.disable();
        }
        else
        {
            createTemplateButton.enable();
        }
        
        storeGrid1.on("datachanged", function() {
            if (storeGrid1.getCount() == 0 && storeGrid2.getCount() == 0)
            {
                createTemplateButton.disable();
            }
            else
            {
                createTemplateButton.enable();
            }
        })
        
        storeGrid2.on("datachanged", function() {
            if (storeGrid1.getCount() == 0 && storeGrid2.getCount() == 0)
            {
                createTemplateButton.disable();
            }
            else
            {
                createTemplateButton.enable();
            }
        })
    },
    
    _copySessions: function(button, config, fake)
    {
        let sourceStore = button.ownerCt.prev().items.get(0).store;
        let targetStore = button.ownerCt.next().items.get(0).store;
        
        let dataThatRequiresAServerConversion = [];
        let toReplace = {};
        let newRecords = {};
        
        for (let i=0; i < sourceStore.getCount(); i++)
        {
            let record = sourceStore.getAt(i);
            if (record.get(config.authorizeCopy) != true && record.get("__notEditable") !== true)
            {
                let newRecord = targetStore.getModel().create();
                
                let data = {};
                
                for (let d in record.data)
                {
                    if (d != 'id' && d != config.authorizeCopy)
                    {
                        if (!(config.doNotCopy || []).includes(d))
                        {
                            if (targetStore.getModel().getField(d) != null)
                            {
                                // Direct copy
                                data[d] = record.data[d];
                                
                                if (record.data[d + "_repeater"])
                                {
                                    data[d + "_repeater"] = record.data[d + "_repeater"];
                                }
                            }
                        }
                        else if (typeof record.data[d] == 'string' && record.data[d])
                        {
                            toReplace[newRecord.getId()] = toReplace[newRecord.getId()] || [];
                            toReplace[newRecord.getId()].push(d);
                             
                            data[d] = record.data[d];
                            if (!dataThatRequiresAServerConversion.includes(record.data[d]))
                            {
                                // Require a server conversion of the value
                                dataThatRequiresAServerConversion.push(record.data[d]);
                            }
                        }
                    }
                }
                
                newRecords[newRecord.getId()] = {
                    record: newRecord,
                    data: data
                }
            }
        }
        
        if (fake)
        {
            return Object.keys(newRecords).length;
        }
        debugger
        if (dataThatRequiresAServerConversion.length == 0)
        {
            this._copySessionsStep2(null, {store: targetStore, newRecords: newRecords, toReplace: toReplace});
        }
        else
        {
            Ametys.data.ServerComm.callMethod({
                role: "org.ametys.plugins.odfpilotage.helper.PilotageHelper",
                methodName: "getCompatibleModalityInSession2",
                parameters: [dataThatRequiresAServerConversion],
                callback: {
                    handler: this._copySessionsStep2,
                    scope: this,
                    arguments: {
                        store: targetStore,
                        newRecords: newRecords,
                        toReplace: toReplace
                    }
                },
                errorMessage: true
            });            
        }
    },
    
    _copySessionsStep2: function(serverData, args)
    {
        let store = args.store;
        let newRecords = args.newRecords;
        let toReplace = args.toReplace;
        
        for (let newRecordId in newRecords)
        {
            let newRecord = newRecords[newRecordId].record;
            let data = newRecords[newRecordId].data;
            
            store.add(newRecord);
            newRecord.set(data); // setting data after, to be not commited
            
            if (serverData && toReplace[newRecord.getId()])
            {
                for (let k of toReplace[newRecord.getId()])
                {
                    newRecord.set(k, serverData[newRecord.get(k)] || null);
                }
            }
            
            Ametys.plugins.cms.search.SearchGridRepeaterDialog._markAllAsModified(null, newRecord); // to ensure, empty data have the red flag
        }
    },
    
    _ok: function (dialog, parentRecord, grids, dataIndex, contentId, callback)
    {
        let repeaterValuesAll = {};
        
        for (let i=0; i < grids.length; i++)
        {
            // Set educational path on the hidden field 'path'
            let educationalPath = this._getEducationalPath(parentRecord, dataIndex);
            for (let item of grids[i].getStore().getData().items)
            {
                if (item.get('common') === undefined)
                {
                    // Untouched old values, will be interpreted by server as "empty values"... therefore, they will not have their default value anymore ODF-3924
                    item.set('common', true, {silent: true});
                }
                
                if (!item.get('path') && item.get('common') === false)
                {
                    item.set('path', educationalPath, {silent: true});    
                }
            }
        
            var entriesValues = Ametys.plugins.cms.search.SearchGridRepeaterDialog._gridToValues(grids[i]);
            if (entriesValues == null)
            {
                Ametys.log.ErrorDialog.display({
                    title: "{{i18n plugin.cms:UITOOL_CONTENTEDITIONGRID_REPEATER_VALUE_ERROR_TITLE}}",
                    text: "{{i18n plugin.cms:UITOOL_CONTENTEDITIONGRID_REPEATER_VALUE_ERROR_DESC}}" + "<br/>" + grids[i].ownerCt.getTitle(),
                    details: "The repeater n°" + i + " has some invalid values",
                    category: this.self.getName()
                });
                
                return;
            }
            
            // Replace the initialy filtered data
            for (let elimanatedRecord of this._eliminatedRecordsForEducationPath[i])
            {
                entriesValues.push(elimanatedRecord.values);
            }
            
            entriesValues.sort(function(a , b) {
                if (a.common !== false && b.common === false)
                {
                    return -1;
                }
                else if (a.common === false && b.common !== false)
                {
                    return +1;
                }
                else if (a.common === false /*&& b.common === false*/ && a.path != b.path)
                {
                    return a.path < b.path ? -1 : 1;
                } 

                return entriesValues.indexOf(a) < entriesValues.indexOf(b) ? -1 : 1;
            })
            
            var repeaterValues = parentRecord.getData()[dataIndex[i] + "_repeater"];
            repeaterValues.entries = [];
            for (var index = 0; index < entriesValues.length; index++)
            {
                let notEditable = entriesValues[index].__notEditable;
                delete entriesValues[index].__notEditable;
                
                repeaterValues.entries[index] = {
                    position: index + 1,
                    values: entriesValues[index]
                };
                
                if (entriesValues[index]['previous-position'] != repeaterValues.entries[index].position)
                {
                    repeaterValues.entries[index]['previous-position'] = entriesValues[index]['previous-position'];
                }
                delete entriesValues[index]['previous-position'];
                
                if (notEditable)
                {
                    repeaterValues.entries[index].notEditable = true;
                }            
            }
            repeaterValuesAll[dataIndex[i]] = repeaterValues;
        }

        if (callback)
        {
            callback(repeaterValuesAll);
            dialog.doNotCallCallback = true;
        }
        
        Ametys.plugins.cms.search.SearchGridRepeaterDialog._closeForced = true;
        dialog.close();
    },
    
    // Override of SearchGridRepeaterDialog used by the _createItems method
    
    _beforeEdit: function(editor, e, eOpts, contentId, contentGridId)
    {
        return Ametys.plugins.cms.search.SearchGridRepeaterDialog._beforeEdit.call(this, editor, e, eOpts, contentId, contentGridId);
    },
    
    _isRecordMetadataNotModifiable: function(contentRecord, metadataPath, fieldName, repeaterRecord, cell)
    {
        return Ametys.plugins.cms.search.SearchGridRepeaterDialog._isRecordMetadataNotModifiable(contentRecord, metadataPath, fieldName, repeaterRecord, cell);
    },
    
    _beforeEditContentCB: function(content, editingPlugin, record, contentGrid)
    {
        if (content == null)
        {   
            Ametys.plugins.cms.search.SearchGridRepeaterDialog._beforeEditContentCB(content, editingPlugin, record, contentGrid);
        }
        else 
        {
            if (content.getAvailableActions().indexOf(this.workflowEditActionId) != -1)
            {
                Ametys.plugins.cms.search.SearchGridRepeaterDialog._beforeEditContentCB(content, editingPlugin, record, contentGrid);
            }
            else
            {
                // Test if edit workflow action id is available for current path
                Ametys.data.ServerComm.callMethod({
                    role: "org.ametys.plugins.odfpilotage.helper.MCCCourseTreeGridHelper",
                    methodName: "canEditRepeaterWithPath",
                    parameters: [
                        content.getId(),
                        record.get("educationalPaths")[0].path.split(";")
                    ],
                    callback: {
                        handler: this._canEditRepeaterWithPathCB,
                        scope: this,
                        arguments: {
                            content: content,
                            editingPlugin: editingPlugin, 
                            record: record,
                            contentGrid: contentGrid
                        }
                    },
                    errorMessage: true,
                    waitMessage: false
                });
            }
        }
    },
    
    _canEditRepeaterWithPathCB: function (available, args)
    {
        // Add edit workflow action id to available actions
        let availableActions = args.content.getAvailableActions();
        if (available)
        {
            availableActions.push(args.contentGrid.ownerGrid.workflowEditActionId);   
        }
        args.content._availableActions = availableActions;
        
        Ametys.plugins.cms.search.SearchGridRepeaterDialog._beforeEditContentCB(args.content, args.editingPlugin, args.record, args.contentGrid);
    },
    
    _cancelEdit: function(editor, e, eOpts, contentId, contentGridId)
    {
        return Ametys.plugins.cms.search.SearchGridRepeaterDialog._cancelEdit(editor, e, eOpts, contentId, contentGridId);
    },
    
    _edit: function(editor, e, eOpts, contentId, contentGridId)
    {
        return Ametys.plugins.cms.search.SearchGridRepeaterDialog._edit(editor, e, eOpts, contentId, contentGridId);
    },
    
    _validateEdit: function (editor, context)
    {
        return Ametys.plugins.cms.search.SearchGridRepeaterDialog._validateEdit(editor, context);
    }
});