// ==UserScript==
// @name         ResetEra Live Thread
// @namespace    http://madjoki.com
// @version      4.0.15
// @description  Update threads without refreshing
// @author       Madjoki
// @match        https://metacouncil.com/threads/*
// @match        https://www.resetera.com/threads/*
// @match        https://bbs.io-tech.fi/threads/*
// @require      https://cdnjs.cloudflare.com/ajax/libs/favico.js/0.3.10/favico.min.js
// @grant        none
// ==/UserScript==
(function () {
    'use strict';
    let favicon;
    // This is to disable scrolldown behaviour when XenForo insert "new messages" box.
    const original = XF.Message.insertMessages;
    XF.Message.insertMessages = function (dataHtml, $container, ascending, onInsert)
    {
        console.log(dataHtml, $container, ascending, onInsert);
        if (dataHtml.content.indexOf('js-newMessagesIndicator') > -1)
            return;
        original(dataHtml, $container, ascending, onInsert);
    }
    var favIconUpdate = function (count) {
        favicon.badge(count);
        favicon.badge(count);
    }
    if (window.location.host === 'www.resetera.com') {
        // Chrome Fix
        //let icon = $('link[rel*=icon]').first().clone();
        //$('link[rel*=icon]').remove();
        //$('head').append(icon);
        favicon = new Favico({
            animation: 'none',
            fontFamily: 'FontAwesome',
            fontStyle: 'normal'
        });
    }
    else {
        favicon = new Favico({
            animation: 'none',
            fontFamily: 'FontAwesome',
            fontStyle: 'normal'
        });
    }
    favIconUpdate();
    var timeoptions = [
        {
            name: "5s",
            value: 5,
        },
        {
            name: "10s",
            value: 10,
        },
        {
            name: "15s",
            value: 15,
        },
        {
            name: "30s",
            value: 30,
        },
        {
            name: "1m",
            value: 60,
        },
        {
            name: "2m",
            value: 120,
        },
    ];
    let defaults = {
        timer: 5,
        enabledByDefault: false,
    };
    let threadID = $('html').data('content-key');
    let userSettings = {}
    let threadSettings = {}
    let recentErrors = 0;
    let countNewMessages = 0;
    let updating = false;
    let enabled = false;
    let paused = false;
    let currentTimer = 120;
    let hasFocus = true;
    // Read Global Settings
    let settingsJson = localStorage.getItem("livethreadSettings");
    if (settingsJson !== null)
        userSettings = JSON.parse(settingsJson) || {};
    // Read Thread Settings
    let threadJson = localStorage.getItem("livethread_" + threadID);
    if (threadJson !== null)
        threadSettings = JSON.parse(threadJson) || {};
    let currentSettings = {}
    function updateSettings() {
        currentSettings = {
            ...defaults,
            ...userSettings,
            ...threadSettings
        }
        if (!("enabled" in currentSettings))
            currentSettings.enabled = currentSettings.enabledByDefault;
        if (!currentSettings.timer || currentSettings.timer < 0)
            currentSettings.enabled = false;
        enabled = currentSettings.enabled;
        paused = !enabled;
    }
    updateSettings();
    currentTimer = currentSettings.timer;
    function getPages(dom) {
        return {
            current: parseInt(dom.find('li.pageNav-page--current').first().text(), 10) || 0,
            next: parseInt(dom.find('.pageNav-page.pageNav-page--later').first().text()) || parseInt(dom.find('.pageNav-page').last().text()) || 0,
            last: parseInt(dom.find('.pageNav-page').last().text()) || 0
        };
    }
    function updateFavIcon() {
        if (countNewMessages > 0) {
            favIconUpdate(countNewMessages);
        }
        else if (currentSettings.enabled && !paused) {
            favIconUpdate('');
        }
        else {
            favIconUpdate(0);
        }
    }
    function addoptions(el, values) {
        $(el).find("option").remove();
        $(values).each(function (i, o) {
            $(el).append($("<option>", {text: o.name, value: o.value}));
        })
    }
    // CSS
    $('body').append(`<style>
    #livethreadPanel {
        display: none;
        text-align: center;
    }
    #livethreadPanel ul {
        display: inline-block;
        margin-bottom: 15px;
    }
    #livethreadPanel ul li {
        display: block;
        text-align: left;
    }
    #updateTime {
        margin-left: 5px;
        padding: 0px;
    }
    #updateTimeDefault {
        margin-left: 5px;
        padding: 0px;
    }
    body.darktheme #livethreadPanel ul {
       color: #8e50be;   /*dark theme only*/
    }
    .livethreadStatus {
        text-align: center;
    }
    .liveThread_enabled .globalAction {
        display: none !important;
    }
    .liveThreadControls a {
        padding: 5px;
    }
</style>`);
    function getTimeOfLastMessage()
    {
        return $('article.message time').last().data('time');
    }
    function getPageUrl(page)
    {
        $('meta[property="og:url"]').attr('content') + `page-${page}`;
    }
    // Get date of last message
    var $lastDate = $('input[name="last_date"]');
    var $container = $('.js-replyNewMessageContainer');
    var pages = getPages($('body'));
    var lastPageWithData = pages.current;
    // If zero messages, it's non thread page like reply page
    if ($('article.message').length === 0)
        return;
    // Pause if this isn't last page
    if (pages.current !== pages.last)
        paused = true;
    // Create Control Panel
    var controlsContainer = $('<div>', { class: 'block-outer-opposite liveThreadControls' });
    var statusText = $('<a>', { href: '#', class: 'livethreadStatus livethreadRefresh postsRemaining' });
    var startPauseBtn = $('<a>', { href: '#', class: 'livethreadStartPause' }).append($('<i>', { class: 'fa' }));
    var settingsBtn = $('<a>', { href: '#', class: 'livethreadSettings' }).append($('<i>', { class: 'fa fa-cog' }));
    var refreshBtn = $('<a>', { href: '#', class: 'livethreadRefresh' }).append($('<i>', { class: 'fa fa-refresh' }));
    controlsContainer.append(statusText);
    controlsContainer.append(startPauseBtn);
    controlsContainer.append(refreshBtn);
    controlsContainer.append(settingsBtn);
    $('.block-outer.block-outer--after').append(controlsContainer);
    // Build Settings
    $('.block-outer.block-outer--after').last().after('\
<div id="livethreadPanel" class="DiscussionListOptions secondaryContent">\
    <h2 class="heading h1">This Thread</h2>\
    <ul>\
       <li><label for="updateTime">Update Speed:</label> <select id="updateTime" class="textCtrl"></select></li>\
    </ul>\
    <h2 class="heading h1">Global Settings</h2>\
    <ul>\
			<li style="display: none"><label><input type="checkbox" id="liveThread_remember" value="1"> Remember New Threads by Default</label></li>\
			<li><label><input type="checkbox" id="liveThread_enableByDefault" value="1"> Enable By Default</label></li>\
			<li><label>Default Update Speed: <select id="updateTimeDefault" class="textCtrl"></select></label></li>\
			<li style="display: none"><label><input type="checkbox" id="liveThread_debug" value="1"> Log Debug Data to Console (only for testing)</label></li>\
    </ul>\
</div>');
    function saveSettings()
	{
        localStorage.setItem("livethread_" + threadID, JSON.stringify(threadSettings));
        localStorage.setItem("livethreadSettings", JSON.stringify(userSettings));
        updateForm();
	}
    $('#liveThread_enableByDefault').change(function () {
        userSettings.enabledByDefault = $('#liveThread_enableByDefault').is(':checked');
        saveSettings();
    });
    $('#liveThread_messageMarkers').change(function () {
        userSettings.useNewMessageMarker = $('#liveThread_messageMarkers').is(':checked');
        saveSettings();
    });
    $('#liveThread_remember').change(function () {
        userSettings.rememberThreads = $('#liveThread_remember').is(':checked');
        saveSettings();
    });
    $('#liveThread_debug').change(function () {
        userSettings.enableDebug = $('#liveThread_debug').is(':checked');
        saveSettings();
    });
    $('#updateTime').change(function () {
        const time = parseInt($('#updateTime').val());
        if (time)
            threadSettings.timer = parseInt(time);
        else
            delete threadSettings.timer;
		saveSettings();
    });
    $('#updateTimeDefault').change(function () {
        userSettings.timer = parseInt($('#updateTimeDefault').val());
		saveSettings();
    });
    // Control Panel
    function updateForm()
    {
        addoptions($("#updateTime"), [{
            name: "Default",
            value: 0,
        }, {
            name: "Disabled",
            value: -1,
        }, ...timeoptions]);
        addoptions($("#updateTimeDefault"), timeoptions);
        $("#updateTime option[value='" + threadSettings.timer + "']").attr("selected", true);
        $("#updateTimeDefault option[value='" + userSettings.timer + "']").attr("selected", true);
        $("#liveThread_remember").attr("checked", userSettings.rememberThreads);
        //$("#liveThread_messageMarkers").attr("checked", userSettings.useNewMessageMarker);
        $("#liveThread_enableByDefault").attr("checked", userSettings.enabledByDefault);
        //$('#liveThread_currentRemember').attr("checked", isRememberedThread);
        //$("#liveThread_debug").attr("checked", globalSettings.enableDebug);
    }
    updateForm();
    function insertMessagesAlternative(data) {
        console.log(data);
        var html = $.parseHTML(data.html.content);
        var $html = $(html);
        var pagesNew = getPages($html);
        if (pagesNew.current !== pages.current)
        {
            console.log("page changed", pagesNew, pages);
            pages = pagesNew;
            lastPageWithData = pages.current;
            history.pushState({}, "", `page-${pages.current}`);
            var $navNew = $html.find('.pageNavWrapper').first();
            $('.pageNavWrapper').html($navNew.html());
        }
        $html.find('article.message').each(function () {
            insertMessage($(this), $container, true);
        });
        updateFavIcon();
        updating = false;
    }
    function insertMessages(data) {
        if (data.message)
        {
            recentErrors++;
            return;
        }
        if (data.lastDate)
            $lastDate.val(data.lastDate);
        recentErrors = 0;
        if (data.html) {
            XF.setupHtmlInsert(data.html, function ($html, container, onComplete, onInsert) {
                // TODO: Check if DIV is there and load additional messages automatically
                var div = $html.children('div');
                if (div.length)
                {
                    console.log(div);
                }
                $html.each(function () {
                    if (!this.tagName) {
                        return;
                    }
                    if (this.tagName === 'DIV') {
                        console.log(this);
                        var $msg = $(this);
                        // TEMP
                        $container.append(this);
                    }
                    insertMessage($(this), $container, true);
                });
                if (onInsert) {
                    onInsert($html);
                }
                updateFavIcon();
                updating = false;
            });
        }
    }
    function insertMessage($message, $container, ascending) {
        if (!$message.data('author')) // Fix for empty messages
            return;
        // post-15795528
        var id = $message.attr('id');
        var $msg = $(`#${id}`);
        if ($msg.length)
        {
            console.log(`not inserting ${id}, already in page`);
            // TODO: update
            return;
        }
        countNewMessages++;
        var $firstChild = $container.children().first();
        //$message.hide();
        if ($firstChild.is('form') && !ascending) {
            $message.insertAfter($firstChild);
        }
        else if (!ascending) {
            $container.prepend($message);
        }
        else {
            $container.append($message);
        }
        //$message.xfFadeDown();
        $message.addClass('livethread_unread');
        XF.activate($message);
    }
    function loadMessages() {
        if (updating)
            return;
        if (lastPageWithData !== pages.last)
            loadMessagesAlternative();
        else
            loadMessagesFast();
        updating = true;
    }
    // Use api to get messages
    function loadMessagesFast() {
        XF.ajax('GET', 'new-posts', { after: getTimeOfLastMessage() }, insertMessages).always(function () { updating = false }, {useError: false});
        updateControls();
    }
    function loadMessagesAlternative() {
        const page = pages.next || pages.current;
        XF.ajax('GET', `page-${page}`, insertMessagesAlternative).always(function () { updating = false }, {useError: false});
    }
    function timer() {
        if (paused || !enabled)
            return;
        currentTimer--;
        // Delay if there's recent errors
        var errorDelay = 10000 * Math.min(5, recentErrors);
        if (currentTimer === 0) {
            loadMessages();
            currentTimer = currentSettings.timer + errorDelay;
        }
        updateControls();
    }
    function getStatusText() {
        var status = "";
        if (updating)
            status += "Updating";
        else if (currentTimer && !paused && enabled) {
            status += "Next Update In " + currentTimer + " seconds";
            //if (countNewLast > 0)
            //    status += " - " + countNewLast + " New Messages!";
        }
        else
            status = "Disabled";
        return status;
    }
    function updateControls() {
        $(".livethreadStartPause i").toggleClass('fa-pause', !paused);
        $(".livethreadStartPause i").toggleClass('fa-play', paused);
        $(".livethreadRefresh i").toggleClass('fa-spin', updating);
        $(".livethreadStatus").text(getStatusText());
        $('body').toggleClass('liveThread_enabled', !paused);
    }
    function isvisible($ele) {
        var lBound = $(window).scrollTop(),
            uBound = lBound + $(window).height(),
            top = $ele.offset().top,
            bottom = top + $ele.outerHeight(true);
        return (top > lBound && top < uBound) || (bottom > lBound && bottom < uBound) || (lBound >= top && lBound <= bottom) || (uBound >= top && uBound <= bottom);
    }
    function handleScroll() {
        $('.livethread_unread').each(function (i, el) {
            var $el = $(el);
            if (isvisible($el)) {
                $el.removeClass('livethread_unread');
                $el.prevAll('.livethread_unread').removeClass('livethread_unread');
            }
        });
        countNewMessages = $('.livethread_unread').length;
        updateFavIcon();
    }
    $(window).scroll(function () {
        handleScroll();
    });
    $(window).focus(function () {
        handleScroll();
        hasFocus = true;
    });
    $(window).focusout(function () {
        handleScroll();
        hasFocus = false;
    });
    updateControls();
    setInterval(timer, 1000);
    $('.livethreadRefresh').click(function (event) {
        event.preventDefault();
        loadMessages();
    });
     $('.livethreadStartPause').click(function (event) {
        event.preventDefault();
        enabled = true;
        paused = !paused;
        updateControls();
    });
    $('.livethreadSettings').click(function (event) {
        event.preventDefault();
        $('#livethreadPanel').toggle();
        //$('#livethreadPanel').scrollintoview();
    });
})();