// SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
//
// SPDX-License-Identifier: AGPL-3.0-or-later

(function() {
    var CKEDITOR = window.CKEDITOR;

    function isUnstylable(el) {
        if (el.hasClass('cke_widget_mathjax')) {
            return false;
        }
        if (el.hasClass('cke_widget_mediatag')) {
            return false;
        }
        var b = el.getAttribute('contentEditable') === 'false' ||
            el.getAttribute('data-nostyle');
        return b;
    }

    // COPYPASTED from mediatag-plugin-dialog.js
    var isReadOnly = function (el) {
        if (!el) { return; }
        var parent = el;
        while (parent) {
            if (parent.nodeName.toUpperCase() === 'BODY') {
                return parent.getAttribute("contenteditable") === 'false';
            }
            parent = parent.parentElement;
        }
    };

    var color1 = 'rgba(249, 230, 65, 1.0)';
    var color2 = 'rgba(252, 181, 0, 1.0)';

    CKEDITOR.plugins.add('comments', {
        onLoad: function() {
            CKEDITOR.addCss('comment { background-color: ' + color1 + '; color:#333; }' +
                '@keyframes color { 0% { background-color: ' + color2 + '; } 50% { background-color: ' + color1 + '; } 100% { background-color: ' + color2 + '; } }' +
                'comment.active { animation-name: color; animation-duration: 1s; animation-iteration-count: 2; background-color: ' + color2 + '; outline: none;}' +
                'comment media-tag { border: 2px solid ' + color1 + ' !important; }' +
                'comment.active media-tag { border: 2px solid ' + color2 + ' !important; }' +
                'comment * { background-color: transparent !important; }');
        },
        init: function(editor) {
            var Messages = CKEDITOR._commentsTranslations;

            var styleDef = {
                element: 'comment',
                attributes: {
                    'data-uid': '#(uid)',
                },
                overrides: [{
                    element: 'comment'
                }],
                childRule: isUnstylable
            };
            var removeStyle = new CKEDITOR.style(styleDef, { 'uid': '' });

            var isApplicable = editor.plugins.comments.isApplicable = function(path, sel) {
                path = path || editor.elementPath();
                sel = sel || editor.getSelection();
                var applicable = removeStyle.checkApplicable(path, editor);

                var selectedHtml = editor.getSelectedHtml();
                if (selectedHtml === null) { return; }
                var comments = selectedHtml.$.querySelectorAll('comment');
                var hasComments = comments && comments.length;

                var isComment = removeStyle.checkActive(path, editor);
                var empty = !sel.getSelectedText();
                return applicable && !empty && !hasComments && !isComment;
            };

            // Register the command.
            editor.plugins.comments.command = editor.addCommand('comment', {
                exec: function(editor) {
                    if (editor.readOnly) { return; }
                    editor.focus();

                    var uid = CKEDITOR.tools.getUniqueId();
                    editor.plugins.comments.addComment(uid, function() {
                        // Make an undo spnashot
                        editor.fire('saveSnapshot');
                        // Make sure comments won't overlap
                        editor.removeStyle(removeStyle);

                        // Add the comment marker
                        var s = new CKEDITOR.style(styleDef, { 'uid': uid });
                        editor.applyStyle(s);

                        // Save the undo snapshot after all changes are affected.
                        setTimeout(function() {
                            editor.fire('saveSnapshot');
                        }, 0);
                    });

                }
            });

            // Uncomment provided element
            editor.plugins.comments.uncomment = function(id, els) {
                if (editor.readOnly) { return; }
                editor.fire('saveSnapshot');

                //Create style for this id
                var style = new CKEDITOR.style({
                    element: 'comment',
                    attributes: {
                        'data-uid': id,
                    },
                });
                style.alwaysRemoveElement = true;
                els.forEach(function(el) {
                    // Create range for this element
                    el.removeAttribute('class');
                    var node = new CKEDITOR.dom.node(el);
                    var range = editor.createRange();
                    range.setStart(node, 0);
                    range.setEnd(node, Number.MAX_SAFE_INTEGER);
                    // Remove style for the comment
                    try {
                        style.removeFromRange(range, editor);
                    } catch (e) {
                        console.error(e);
                    }
                });

                setTimeout(function() {
                    editor.fire('saveSnapshot');
                }, 0);
            };

            // Uncomment from context menu, disabled for now...
            editor.addCommand('uncomment', {
                exec: function(editor, data) {
                    if (editor.readOnly) { return; }
                    editor.fire('saveSnapshot');
                    if (!data ||  !data.id) {
                        editor.focus();
                        editor.removeStyle(removeStyle);
                        setTimeout(function() {
                            editor.fire('saveSnapshot');
                        }, 0);
                        return;
                    }
                }
            });

            // Register the toolbar button.
            if (editor.ui.addButton) {
                editor.ui.addButton('Comment', {
                    label: Messages.comment,
                    command: 'comment',
                    icon: '/pad/icons/comment.png',
                    toolbar: 'insert,10'
                });
            }

            if (editor.addMenuItems) {
                editor.addMenuGroup('comments');
                editor.addMenuItem('comment', {
                    label: Messages.comment,
                    icon: '/pad/icons/comment.png',
                    command: 'comment',
                    group: 'comments'
                });
                /*
                editor.addMenuItem('uncomment', {
                    label: Messages.uncomment,
                    icon : '/pad/icons/uncomment.png',
                    command: 'uncomment',
                    group: 'comments'
                });
                */
            }
            if (editor.contextMenu) {
                /*
                editor.contextMenu.addListener(function (element, sel, path) {
                    var isComment = removeStyle.checkActive(path, editor);
                    if (!isComment) { return; }
                    return {
                        uncomment: CKEDITOR.TRISTATE_OFF,
                    };
                });
                */
                editor.contextMenu.addListener(function(element, sel, path) {
                    var applicable = isApplicable(path, sel);
                    if (!applicable || isReadOnly(element.$)) { return; }

                    return {
                        comment: CKEDITOR.TRISTATE_OFF,
                    };
                });
            }
        }
    });

})();
