if(!Umi.Parser) Umi.Parser = {};
if(!Umi.Parser.SockChatBBcode) Umi.Parser.SockChatBBcode = {};

const UmiBBCodes = [
    {
        tag: 'b',
        text: 'B',
        style: 'font-weight: 700',
        replace: '<b>{0}</b>',
    },
    {
        tag: 'i',
        text: 'I',
        style: 'font-style: italic',
        replace: '<i>{0}</i>',
    },
    {
        tag: 'u',
        text: 'U',
        style: 'text-decoration: underline',
        replace: '<u>{0}</u>',
    },
    {
        tag: 's',
        text: 'S',
        style: 'text-decoration: line-through',
        replace: '<del>{0}</del>',
    },
    {
        tag: 'quote',
        text: 'Quote',
        replace: '<q style="font-variant: small-caps;">{0}</q>',
    },
    {
        tag: 'code',
        text: 'Code',
        replace: '<span style="white-space: pre-wrap; font-family: monospace;">{0}</span>',
    },
    {
        tag: 'sjis',
        replace: '<span class="sjis" style="white-space: pre-wrap;">{0}</span>',
    },
    {
        tag: 'color',
        text: 'Colour',
        hasArg: true,
        stripArg: ';:{}<>&|\\/~\'"',
        replace: '<span style="color:{0};">{1}</span>',
    },
    {
        tag: 'bgcolor',
        hasArg: true,
        stripArg: ';:{}<>&|\\/~\'"',
        replace: '<span style="background-color:{0};">{1}</span>',
    },
    {
        tag: 'img',
        text: 'Image',
        stripText: '"\'',
        replace: '<span title="{0}"><span title="link"><a class="markup__link" href="{0}" target="_blank" rel="nofollow noreferrer noopener">{0}</a></span>&nbsp;[<a href="#" onclick="Umi.Parser.SockChatBBcode.EmbedImage(this);return false;" class="markup__link">Embed</a>]</span>',
    },
    {
        tag: 'url',
        stripText: '"\'',
        replace: '<a href="{0}" target="_blank" rel="nofollow noreferrer noopener" class="markup__link">{0}</a>',
    },
    {
        tag: 'url',
        text: 'URL',
        hasArg: true,
        stripArg: '"\'',
        replace: '<a href="{0}" target="_blank" rel="nofollow noreferrer noopener" class="markup__link">{1}</a>',
    },
    {
        tag: 'video',
        text: 'Video',
        stripText: '"\'',
        replace: '<span title="{0}"><span title="link"><a class="markup__link" href="{0}" target="_blank" rel="nofollow noreferrer noopener">{0}</a></span>&nbsp;[<a href="#" onclick="Umi.Parser.SockChatBBcode.EmbedVideo(this);return false;" class="markup__link">Embed</a>]</span>',
    },
    {
        tag: 'audio',
        text: 'Audio',
        stripText: '"\'',
        replace: '<span title="{0}"><span title="link"><a class="markup__link" href="{0}" target="_blank" rel="nofollow noreferrer noopener">{0}</a></span>&nbsp;[<a href="#" onclick="Umi.Parser.SockChatBBcode.EmbedAudio(this);return false;" class="markup__link">Embed</a>]</span>',
    },
    {
        tag: 'spoiler',
        text: 'Spoiler',
        stripText: '"\'',
        replace: '<span data-shit="{0}"><span>*** HIDDEN ***</span>&nbsp;[<a href="#" onclick="Umi.Parser.SockChatBBcode.ToggleSpoiler(this);return false;" class="markup__link">Reveal</a>]</span>',
    },
];

Umi.Parsing = (function() {
    const replaceAll = function(haystack, needle, replace, ignore) {
        return haystack.replace(
            new RegExp(
                needle.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g, '\\$&'),
                (ignore ? 'gi' : 'g')
            ),
            (typeof (replace) == 'string')
                ? replace.replace(/\$/g, '$$$$')
                : replace
         );
    }
    const stripChars = function(str, chars) {
        if(!chars)
            return str;

        for(let i = 0; i < chars.length; i++)
            str = replaceAll(str, chars[i], '');

        return str;
    }

    const extractMotiv = function(elem) {
        let topText = 'Top Text';
        let bottomText = 'Bottom Text';

        const root = elem.closest('.message');
        if(root instanceof Element && 'body' in root.dataset) {
            const msgText = root.dataset.body.replace(/\[(.*?)\](.*?)\[\/(.*?)\]/g, '').trim();

            if(msgText.length > 0) {
                const msgTextParts = msgText.split(' ');
                const topTextLength = Math.ceil(msgTextParts.length / 10);
                const topTextParts = msgTextParts.slice(0, topTextLength);
                let bottomTextParts = null;

                if(msgTextParts.length === 1 || Math.random() > .7) {
                    bottomTextParts = msgTextParts;
                } else {
                    bottomTextParts = msgTextParts.slice(topTextLength);
                }

                topText = topTextParts.join(' ');
                bottomText = bottomTextParts.join(' ');
            }
        }

        return {
            top: topText,
            bottom: bottomText,
        };
    };
    const motivFrame = function(texts, body) {
        return $element(
            'div',
            {
                style: {
                    display: 'inline-block',
                    textAlign: 'center',
                    fontFamily: '\'Times New Roman\', serif',
                    backgroundColor: 'black',
                    fontVariant: 'small-caps',
                    fontSize: '1.3em',
                    lineHeight: '1.4em',
                },
            },
            $element(
                'div',
                {
                    style: {
                        border: '3px double #fff',
                        maxWidth: '50vw',
                        maxHeight: '50vh',
                        marginTop: '30px',
                        marginLeft: '50px',
                        marginRight: '50px',
                        boxSizing: 'content-box',
                        display: 'inline-block',
                    },
                },
                body
            ),
            $element(
                'h1',
                {
                    style: {
                        color: '#fff',
                        textDecoration: 'none !important',
                        margin: '10px',
                        textTransform: 'uppercase',
                    },
                },
                texts.top
            ),
            $element(
                'p',
                {
                    style: {
                        color: '#fff',
                        textDecoration: 'none !important',
                        margin: '10px',
                    },
                },
                texts.bottom
            ),
        );
    };

    const toggleImage = function(element) {
        const url = element.parentElement.title;
        const container = element.parentElement.getElementsByTagName('span')[0];
        const anchor = container.getElementsByTagName('a')[0];
        const isEmbedded = container.title !== 'link';

        if(isEmbedded) {
            container.title = 'link';
            element.textContent = 'Embed';
            element.dataset.embed = '0';
            anchor.textContent = url;
        } else {
            container.title = 'image';
            element.textContent = 'Remove';
            element.dataset.embed = '1';
            element.classList.add('markup__link--visited');

            let html = $element(
                'img',
                {
                    src: url,
                    alt: url,
                    style: {
                        maxWidth: '50vw',
                        maxHeight: '50vh',
                        verticalAlign: 'middle',
                    },
                    onload: () => {
                        if(mami.settings.get('autoScroll'))
                            container.scrollIntoView({ inline: 'end' });
                    },
                },
            );

            if(mami.settings.get('motivationalImages'))
                html = motivFrame(
                    extractMotiv(element),
                    html
                );

            anchor.textContent = '';
            anchor.appendChild(html);
        }
    };
    const toggleAudio = function(element) {
        const url = element.parentElement.title;
        const container = element.parentElement.getElementsByTagName('span')[0];
        const isEmbedded = container.title !== 'link';

        if(isEmbedded) {
            container.title = 'link';
            element.dataset.embed = '0';
            element.textContent = 'Embed';
            container.textContent = '';
            container.appendChild($element(
                'a',
                {
                    href: url,
                    target: '_blank',
                    rel: 'nofollow noreferrer noopener',
                    className: 'markup__link',
                },
                url,
            ));
        } else {
            container.title = 'audio';
            element.dataset.embed = '1';
            element.textContent = 'Remove';
            container.textContent = '';
            element.classList.add('markup__link--visited');

            let media = $element(
                'audio',
                {
                    src: url,
                    controls: true,
                    onloadedmetadata: () => {
                        if(mami.settings.get('autoScroll'))
                            container.scrollIntoView({ inline: 'end' });
                        if(mami.settings.get('autoEmbedPlay'))
                            media.play();
                    },
                },
            );

            container.appendChild(media);
        }
    };
    const toggleVideo = function(element) {
        const url = element.parentElement.title;
        const container = element.parentElement.getElementsByTagName('span')[0];
        const isEmbedded = container.title !== 'link';

        if(isEmbedded) {
            container.title = 'link';
            element.dataset.embed = '0';
            element.textContent = 'Embed';
            container.textContent = '';
            container.appendChild($element(
                'a',
                {
                    href: url,
                    target: '_blank',
                    rel: 'nofollow noreferrer noopener',
                    className: 'markup__link',
                },
                url,
            ));
        } else {
            container.title = 'video';
            element.dataset.embed = '1';
            element.textContent = 'Remove';
            element.classList.add('markup__link--visited');

            let media = $element(
                'video',
                {
                    src: url,
                    controls: true,
                    style: {
                        maxWidth: '800px',
                        maxHeight: '600px',
                    },
                    onloadedmetadata: () => {
                        if(mami.settings.get('autoScroll'))
                            container.scrollIntoView({ inline: 'end' });
                        if(mami.settings.get('autoEmbedPlay'))
                            media.play();
                    },
                },
            );

            let html = media;

            if(mami.settings.get('motivationalVideos'))
                html = motivFrame(
                    extractMotiv(element),
                    html
                );

            container.textContent = '';
            container.appendChild(html);
        }
    };
    const toggleSpoiler = function(element) {
        const container = element.parentElement;
        const target = container.querySelector('span');

        if(container.dataset.revealed === 'yes') {
            container.dataset.revealed = 'no';
            target.textContent = '*** HIDDEN ***';
            element.dataset.embed = '0';
            element.textContent = 'Reveal';
        } else {
            container.dataset.revealed = 'yes';
            target.textContent = container.dataset.shit;
            element.dataset.embed = '1';
            element.textContent = 'Hide';
            element.classList.add('markup__link--visited');
        }
    };

    Umi.Parser.SockChatBBcode.EmbedImage = toggleImage;
    Umi.Parser.SockChatBBcode.EmbedAudio = toggleAudio;
    Umi.Parser.SockChatBBcode.EmbedVideo = toggleVideo;
    Umi.Parser.SockChatBBcode.ToggleSpoiler = toggleSpoiler;

    return {
        Parse: function(element, message) {
            for(let i = 0; i < UmiBBCodes.length; i++) {
                const bbCode = UmiBBCodes[i];

                if(!bbCode.hasArg) {
                    let at = 0;
                    while((at = element.innerHTML.indexOf('[' + bbCode.tag + ']', at)) != -1) {
                        let end;
                        if((end = element.innerHTML.indexOf('[/' + bbCode.tag + ']', at)) != -1) {
                            const inner = stripChars(element.innerHTML.substring(at + ('[' + bbCode.tag + ']').length, end), bbCode.stripText == undefined ? '' : bbCode.stripText);
                            const replace = replaceAll(bbCode.replace, '{0}', inner);
                            element.innerHTML = element.innerHTML.substring(0, at) + replace + element.innerHTML.substring(end + ('[/' + bbCode.tag + ']').length);
                            at += replace.length;
                        } else break;
                    }
                } else {
                    let at = 0;
                    while((at = element.innerHTML.indexOf('[' + bbCode.tag + '=', at)) != -1) {
                        let start, end;
                        if((start = element.innerHTML.indexOf(']', at)) != -1) {
                            if((end = element.innerHTML.indexOf('[/' + bbCode.tag + ']', start)) != -1) {
                                const arg = stripChars(element.innerHTML.substring(at + ('[' + bbCode.tag + '=').length, start), '[]' + (bbCode.stripArg == undefined ? '' : bbCode.stripArg));
                                const inner = stripChars(element.innerHTML.substring(start + 1, end), bbCode.stripText == undefined ? '' : bbCode.stripText);
                                const replace = replaceAll(replaceAll(bbCode.replace, '{1}', inner), '{0}', arg);
                                element.innerHTML = element.innerHTML.substring(0, at) + replace + element.innerHTML.substring(end + ('[/' + bbCode.tag + ']').length);
                                at += replace.length;
                            } else break;
                        } else break;
                    }
                }
            }
        },
    };
})();