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

/**
 * This class handles the errors, warnings or info after content edition
 */
Ext.define(
	"Ametys.cms.content.ContentErrorHelper", 
	{
		singleton: true,
		
        /**
         * Callback function called after edit content server request is processed
         * @param {HTMLElement} response The XML document.
         * @param {HTMLElement} response The XML document.
         * @param {Object} params The callback arguments (see #createContent documentation).
         * @param {Object} additionalFns The additional functions to call for each kind of errors
         * @param {Function} successFn The function to be call to handle success
         * @param {Function} workflowValidationErrorFn The function to be call to handle workflow errors
         * @param {Function} fieldResultErrorFn The function to be call to handle field errors
         * @param {Function} fieldResultWarningFn The function to be call to handle field warning
         * @param {Function} fieldResultInfoFn The function to be call to handle field informations
         * @param {Function} messageFn The function to be call to handle messages (as duplicate content)
         */
        handleContentEditError: function (response, contentId, params, additionalFns)
        {
            var success = Ext.dom.Query.selectValue ('> ActionResult > success', response) == "true";
        
            // Handling workflow errors
            if (Ext.isFunction (additionalFns.workflowValidationErrorFn))
            {
                var workflowErrors = Ext.dom.Query.select ('> ActionResult > workflowValidation > error', response);
                if (!success && workflowErrors.length > 0)
                {
                    var workflowMsgErrors = [];
                    var detailedMsg = '<ul>';
                    for (var i=0; i < workflowErrors.length; i++)
                    {
                        var errorMsg = Ext.dom.Query.selectValue("", workflowErrors[i]);
                        detailedMsg += '<li>' + errorMsg + '</li>';
                        workflowMsgErrors.push(errorMsg);
                    }
                    detailedMsg += '</ul>';
                    
                    var msg = "{{i18n PLUGINS_CMS_SAVE_ACTION_FAILED_WORKFLOW_DESC}}";
                    
                    additionalFns.workflowValidationErrorFn(contentId, msg, detailedMsg, workflowMsgErrors, params);
                    return;
                }
            }
            
            // Handling field errors
            if (Ext.isFunction (additionalFns.fieldResultErrorFn))
            {
                var errors = Ext.dom.Query.select ('> ActionResult > * > fieldResult > error', response);
                if (!success && errors.length > 0)
                {
                    var msg = "{{i18n PLUGINS_CMS_SAVE_ACTION_FAILED_DESC}}";
                    msg += errors.length  == 1 ? "{{i18n PLUGINS_CMS_SAVE_ACTION_FAILED_DESC_SINGLE}}" : errors.length + "{{i18n PLUGINS_CMS_SAVE_ACTION_FAILED_DESC_MULTI}}";
                    
                    var fieldsInError = {};
                    var detailedMsg = this._getFieldsDetailedMessageAndFillFieldMessages(errors, fieldsInError);
                    
                    additionalFns.fieldResultErrorFn(contentId, msg, detailedMsg, fieldsInError, params);
                    return;
                }
            }
            
            // Handling field warnings
            if (Ext.isFunction (additionalFns.fieldResultWarningFn))
            {
                var allWarnings = Ext.dom.Query.select ('> ActionResult > * > fieldResult > warning', response)
                if (!success && allWarnings.length > 0)
                {
                    var fieldsWithWarning = {};
                    var warnings = this._filterBypassedWarnings(allWarnings, params.bypassedWarnings);
                    var hasWarning = warnings.length > 0;
                    var msg = hasWarning
                        ? warnings.length  == 1 ? "{{i18n PLUGINS_CMS_SAVE_ACTION_WARNING_DESC_SINGLE}}" : "{{i18n PLUGINS_CMS_SAVE_ACTION_WARNING_DESC_MULTI}}"
                        : null;
                    var detailedMsg = hasWarning ? this._getFieldsDetailedMessageAndFillFieldMessages(warnings, fieldsWithWarning) : null;
                    var question = hasWarning ? "{{i18n PLUGINS_CMS_SAVE_ACTION_WARNING_DESC_QUESTION}}" : null;
                    
                    additionalFns.fieldResultWarningFn(contentId, msg, detailedMsg, question, fieldsWithWarning, params)
                    return;
                }
            }
            
            // Handling field infos
            if (Ext.isFunction (additionalFns.fieldResultInfoFn))
            {
                var infos = Ext.dom.Query.select ('> ActionResult > * > fieldResult > info', response);
                if (success && infos.length > 0)
                {
                    var msg = "{{i18n PLUGINS_CMS_SAVE_ACTION_FAILED_WORKFLOW_DESC}}TODO";
                    var msg = infos.length  == 1 ? "{{i18n PLUGINS_CMS_SAVE_ACTION_INFO_DESC_SINGLE}}" : "{{i18n PLUGINS_CMS_SAVE_ACTION_INFO_DESC_MULTI}}";

                    var fieldsWithInfo = {};
                    var detailedMsg = this._getFieldsDetailedMessageAndFillFieldMessages(infos, fieldsWithInfo);
                    
                    additionalFns.fieldResultInfoFn(contentId, msg, detailedMsg, fieldsWithInfo, params)
                }
            }
            
            // Handling warning messages
            if (Ext.isFunction (additionalFns.messageFn))
            {
                var messages = Ext.dom.Query.select ('> ActionResult > messages > messages', response);
                if (success && messages.length > 0)
                {
                    var globalLevel = "info";
                    var messagesTab = [];
                    for (var i=0; i < messages.length; i++)
                    {
                        
                        var currentLevel = Ext.dom.Query.selectValue("type", messages[i]);
                        if (globalLevel == "info" && currentLevel == 'warning')
                        {
                            globalLevel = currentLevel;
                        }
    
                        var currentMessages = Ext.dom.Query.select ('message > message', messages[i]);
                        var currentMessage = '';
    
                        for (var j=0; j < currentMessages.length; j++)
                        {
                            currentMessage += Ext.dom.Query.selectValue("", currentMessages[j]);
                        }
                        
                        messagesTab.push({
                            msg: currentMessage,
                            level: currentLevel
                        });
                    }
                    
                    additionalFns.messageFn(contentId, messagesTab, globalLevel, params)
                }
            }
            
            // Success
            if (Ext.isFunction(additionalFns.successFn))
            {
                additionalFns.successFn(contentId, params)
            }
        },
        
        /**
         * @private
         * Retrieves detailed message for given fields
         * @param {HTMLElement[]} fields The XML containing fields and corresponding messages
         * @param {Object} fieldMessages the object to fill with fields' messages
         * @return {String} the detailed message
         */
        _getFieldsDetailedMessageAndFillFieldMessages: function (fields, fieldMessages)
        {
            var detailedMessage = '<ul>';

            for (var i=0; i < fields.length; i++)
            {
                var fieldData = fields[i].parentNode.parentNode;
                var fieldId = fieldData.tagName;
                
                var message = Ext.dom.Query.selectValue("", fields[i]);
                if (fieldId == '_global')
                {
                    detailedMessage += '<li>' + message + '</li>';
                }
                else
                {
                    var fieldPath = Ext.dom.Query.selectValue ('> fieldPath', fieldData);
                    var messages = fieldMessages['content.input.' + (fieldPath || fieldId)] || [];
                    messages.push(message);
                    fieldMessages['content.input.' + (fieldPath || fieldId)] = messages;
                    
                    var fieldLabel = Ext.dom.Query.selectValue ('> fieldLabel', fieldData);
                    detailedMessage += '<li><b>' + (fieldLabel || fieldId) + '</b><br/>' + message + '</li>';
                }
            }
            
            detailedMessage += '</ul>';
            
            return detailedMessage;
        },
        
        /**
         * @private
         * Filter the given warnings to not keep warnings that have already been bypassed
         * @param {HTMLElement[]} allWarnings all the warnings
         * @param {Object} bypassedWarnings warnings that have already been bypassed
         * @return {HTMLElement[]} the filtered warnings 
         */
        _filterBypassedWarnings: function(allWarnings, bypassedWarnings)
        {
            if (Ext.Object.isEmpty(bypassedWarnings))
            {
                // there is no bypassed warnings, retireve all warnings
                return allWarnings;
            }

            var warnings = [];
            for (var i=0; i < allWarnings.length; i++)
            {
                if (!this._hasWarningBeenBypassed(allWarnings[i], bypassedWarnings))
                {
                    warnings.push(allWarnings[i]);
                }
            }
            
            return warnings;
        },
        
        /**
         * @private
         * Checks if the given warning has already been bypassed
         * @param {HTMLElement} warning the warning to check
         * @param {Object} bypassedWarnings warnings that have already been bypassed
         * @return {Boolean} true if the given warning has already been bypassed, false otherwise
         */
        _hasWarningBeenBypassed(warning, bypassedWarnings)
        {
            var warningData = warning.parentNode.parentNode;
            var warningPath = Ext.dom.Query.selectValue ('> fieldPath', warningData);
            
            for (var bypassedWarningId in bypassedWarnings)
            {
                for (var bypassedWarning of bypassedWarnings[bypassedWarningId])
                {
                    if (bypassedWarning.type == 'server' && bypassedWarning.fieldName == 'content.input.' + warningPath)
                    {
                        return true;
                    }
                }
            }
        },
    }
);