(function (sceditor) {
    // Checks if the provided input is a URL we can use for our media tags.
    function isValidURL(candidate) {
        // technically URL.canParse exists, but I'm not sure if other browsers
        // I expect users to use (e.g. Pale Moon) support it. So let's do the
        // old method.
        try {
            const url = new URL(candidate);
            if (url.protocol == 'http:' || url.protocol == 'https:') {
                return true;
            }

            throw "Invalid protocol";
        } catch (e) {
            return false;
        }
    }

    function makeMediaHtml(url, mediatype) {
        if (!isValidURL(url)) {
            return '';
        }
        return '<div class="media-' + mediatype + '">' +
            '<' + mediatype + ' data-src="' + url + '" controls>' +
            '<source src="' + url + '" />' +
            '</' + mediatype + '></div>';
    }

    // This creates a dropdown, similar to the existing YouTube button
    function mediaDropDown(editor, caller, mediatype, urlCallback) {
        // e.g. 'video' -> 'Video'
        const mediaTitle = mediatype.charAt(0).toUpperCase() + mediatype.substring(1).toLowerCase();

        // Container for the text input
        const inputForm = document.createElement("form");

        function clickAction(ev) {
            const medialink = document.getElementById('medialink');
            if (medialink != null && medialink.value != null) {
                // At this point, medialink.value is either a string, or something is very wrong
                if (isValidURL(medialink.value)) {
                    urlCallback(medialink.value);
                }
            }
            editor.closeDropDown(true);
            ev.preventDefault();
        }
        inputForm.addEventListener('submit', clickAction);

        const inputLabel = document.createElement('label');
        inputLabel.htmlFor = 'medialink';
        inputLabel.innerText = mediaTitle + ' URL:';
        inputForm.appendChild(inputLabel);

        const inputElem = document.createElement('input');
        inputElem.id = 'medialink';
        /*
         * It's unlikely users will be repeatedly sending the same audio, and
         * the dropdown will just get in the way.
         */
        inputElem.autocomplete = 'off';
        inputElem.type = 'text';
        inputElem.dir = 'ltr';
        inputElem.placeholder = 'https://';
        inputForm.appendChild(inputElem);

        // "INSERT" button
        const insertDiv = document.createElement("div");
        const insertBtn = document.createElement("input");
        insertBtn.className = 'button';
        insertBtn.type = 'button';
        insertBtn.value = 'Insert';
        insertDiv.appendChild(insertBtn);
        insertBtn.addEventListener('click', clickAction);

        // div to tie the elements together
        const containerDiv = document.createElement("div");
        containerDiv.appendChild(inputForm);
        containerDiv.appendChild(insertDiv);

        editor.createDropDown(caller, 'insertlink', containerDiv);
    }

    // "Converts" the HTML back, by finding the data-src attribute of the media tag
    function htmlToBBCode(element, content, mediatype) {
        const media = element.getElementsByTagName(mediatype);

        if (media.length == 0 || !media[0].attributes.hasOwnProperty('data-src')) {
            return content;
        }

        return '[' + mediatype + ']' + media[0].attributes['data-src'].value + '[/' + mediatype + ']';
    }

    sceditor.formats.bbcode.set(
        'video', {
            tags: {
                div: {
                    class: 'media-video'
                }
            },
            isInline: false,
            allowedChildren: ['#'],
            breakBefore: true,
            breakAfter: true,
            skipLastLineBreak: true,
            format: function (element, content) {
                return htmlToBBCode(element, content, 'video');
            },
            html: function (token, attrs, content) {
                makeMediaHtml(content, 'video');
            }
    });

    sceditor.formats.bbcode.set(
        'audio', {
            tags: {
                div: {
                    class: 'media-audio'
                }
            },
            isInline: false,
            allowedChildren: ['#'],
            breakBefore: true,
            breakAfter: true,
            skipLastLineBreak: true,
            format: function (element, content) {
                return htmlToBBCode(element, content, 'audio');
            },
            html: function (token, attrs, content) {
                makeMediaHtml(content, 'audio');
            }
    });

    sceditor.command.set(
        'video', {
            exec: function (caller) {
                const editor = this;
                mediaDropDown(this, caller, 'video', function (url) {
                    editor.wysiwygEditorInsertHtml(makeMediaHtml(url, 'video'));
                });
            },
            txtExec: function (caller, selected) {
                const editor = this;
                if (isValidURL(selected)) {
                    editor.insertText('[video]' + selected + '[/video]');
                } else {
                    mediaDropDown(this, caller, 'video', function (url) {
                        editor.insertText('[video]' + url + '[/video]');
                    });
                }
            }
        }
    );

    sceditor.command.set(
        'audio', {
            exec: function (caller) {
                const editor = this;
                mediaDropDown(this, caller, 'audio', function (url) {
                    editor.wysiwygEditorInsertHtml(makeMediaHtml(url, 'audio'));
                });
            },
            txtExec: function (caller, selected) {
                const editor = this;
                if (isValidURL(selected)) {
                    editor.insertText('[audio]' + selected + '[/audio]');
                } else {
                    mediaDropDown(this, caller, 'audio', function (url) {
                        editor.insertText('[audio]' + url + '[/audio]');
                    });
                }
            }
        }
    );
})(sceditor);
