(function() {
    'use strict';

    window.IDVE = window.IDVE || {};

    IDVE.RichText = {
        activeEditor: null,
        toolbar: null,
        onChange: null,

        init: function() {
            this.createToolbar();
            document.addEventListener('mousedown', this.handleClickOutside.bind(this));
        },

        createToolbar: function() {
            if (this.toolbar) return;
            var tb = document.createElement('div');
            tb.id = 'idve-richtext-toolbar';
            tb.style.display = 'none';
            tb.innerHTML =
                '<button type="button" data-cmd="bold" title="Bold"><strong>B</strong></button>' +
                '<button type="button" data-cmd="italic" title="Italic"><em>I</em></button>' +
                '<button type="button" data-cmd="underline" title="Underline"><span style="text-decoration:underline">U</span></button>' +
                '<button type="button" data-cmd="strikeThrough" title="Strikethrough"><span style="text-decoration:line-through">S</span></button>' +
                '<span class="idve-toolbar-divider"></span>' +
                '<button type="button" data-cmd="createLink" title="Insert Link">Link</button>' +
                '<button type="button" data-cmd="unlink" title="Remove Link">Unlink</button>' +
                '<span class="idve-toolbar-divider"></span>' +
                '<button type="button" data-cmd="insertUnorderedList" title="Bullet List">UL</button>' +
                '<button type="button" data-cmd="insertOrderedList" title="Numbered List">OL</button>';
            tb.addEventListener('mousedown', function(e) { e.preventDefault(); });
            tb.addEventListener('click', this.handleToolbarClick.bind(this));
            document.body.appendChild(tb);
            this.toolbar = tb;
        },

        handleToolbarClick: function(e) {
            var btn = e.target.closest('button');
            if (!btn) return;
            var cmd = btn.getAttribute('data-cmd');
            if (!cmd) return;

            if (cmd === 'createLink') {
                var url = prompt('Enter URL:');
                if (url) {
                    document.execCommand('createLink', false, url);
                }
            } else {
                document.execCommand(cmd, false, null);
            }
            this.updateToolbarState();
            this.fireChange();
        },

        activate: function(element, onChange) {
            if (this.activeEditor) {
                this.deactivate();
            }
            this.activeEditor = element;
            this.onChange = onChange;
            element.setAttribute('contenteditable', 'true');
            element.focus();
            element.addEventListener('input', this.handleInput.bind(this));
            element.addEventListener('paste', this.handlePaste.bind(this));
            element.addEventListener('keyup', this.updateToolbarState.bind(this));
            element.addEventListener('mouseup', this.updateToolbarState.bind(this));
            this.positionToolbar();
            this.toolbar.style.display = 'flex';
        },

        deactivate: function() {
            if (!this.activeEditor) return;
            var content = this.activeEditor.innerHTML;
            this.activeEditor.removeAttribute('contenteditable');
            this.activeEditor.removeEventListener('input', this.handleInput);
            this.activeEditor.removeEventListener('paste', this.handlePaste);
            this.toolbar.style.display = 'none';
            if (this.onChange) {
                this.onChange(content);
            }
            this.activeEditor = null;
            this.onChange = null;
        },

        handleInput: function() {
            this.fireChange();
        },

        fireChange: function() {
            if (this.activeEditor && this.onChange) {
                this.onChange(this.activeEditor.innerHTML);
            }
        },

        handlePaste: function(e) {
            e.preventDefault();
            var html = (e.clipboardData || window.clipboardData).getData('text/html');
            if (!html) {
                var text = (e.clipboardData || window.clipboardData).getData('text/plain');
                html = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g, '<br>');
            } else {
                html = this.sanitizeHTML(html);
            }
            document.execCommand('insertHTML', false, html);
            this.fireChange();
        },

        sanitizeHTML: function(html) {
            var temp = document.createElement('div');
            temp.innerHTML = html;
            var scripts = temp.querySelectorAll('script,style,iframe,object,embed,form,input,textarea,select');
            for (var i = scripts.length - 1; i >= 0; i--) {
                scripts[i].parentNode.removeChild(scripts[i]);
            }
            // Remove event attributes
            var all = temp.querySelectorAll('*');
            for (var j = 0; j < all.length; j++) {
                var attrs = all[j].attributes;
                for (var k = attrs.length - 1; k >= 0; k--) {
                    var name = attrs[k].name.toLowerCase();
                    if (name.indexOf('on') === 0 || name === 'style' || name === 'class' || name === 'id') {
                        all[j].removeAttribute(attrs[k].name);
                    }
                }
            }
            return temp.innerHTML;
        },

        positionToolbar: function() {
            if (!this.activeEditor || !this.toolbar) return;
            var rect = this.activeEditor.getBoundingClientRect();
            this.toolbar.style.position = 'fixed';
            this.toolbar.style.top = (rect.top - 42) + 'px';
            this.toolbar.style.left = rect.left + 'px';
        },

        updateToolbarState: function() {
            if (!this.toolbar) return;
            var buttons = this.toolbar.querySelectorAll('button[data-cmd]');
            for (var i = 0; i < buttons.length; i++) {
                var cmd = buttons[i].getAttribute('data-cmd');
                try {
                    if (document.queryCommandState(cmd)) {
                        buttons[i].classList.add('active');
                    } else {
                        buttons[i].classList.remove('active');
                    }
                } catch (e) {
                    buttons[i].classList.remove('active');
                }
            }
        },

        handleClickOutside: function(e) {
            if (!this.activeEditor) return;
            if (this.toolbar && this.toolbar.contains(e.target)) return;
            if (this.activeEditor.contains(e.target)) return;
            this.deactivate();
        }
    };
})();
