const adjustTableHeight = () => {
    const tablesContainer = document.getElementById('tables-container');
    if (!tablesContainer)
        return;
    const upperDistance = tablesContainer.getBoundingClientRect().top;

    const tableWrappers = document.getElementsByClassName('table-wrapper');
    for (let i = 0; i < tableWrappers.length; i++) {
        // Ensure we are starting from maximum size prior to calculation.
        tableWrappers[i].style.height = null;
        tableWrappers[i].style.maxHeight = null;

        // Set as a reasonable height, but still allows the user to resize element if they desire.
        const currentHeight = tableWrappers[i].offsetHeight;
        const maxHeight = (window.innerHeight - upperDistance) / Math.min(tableWrappers.length, 4);
        if (currentHeight > maxHeight) {
            tableWrappers[i].style.height = `calc(${maxHeight}px - 1rem)`;
        }

        tableWrappers[i].style.maxHeight = `${currentHeight}px`;
    }
};

/**
 * Convert an integer number of seconds into a human readable HH:MM format
 * @param {Number} seconds
 * @returns {string}
 */
const secondsToHours = (seconds) => {
    let hours = Math.floor(seconds / 3600);
    let minutes = Math.floor((seconds - (hours * 3600)) / 60).toString().padStart(2, '0');
    return `${hours}:${minutes}`;
};

window.addEventListener('load', () => {
    const tables = $(".table").DataTable({
        paging: false,
        info: false,
        dom: "t",
        stateSave: true,
        stateSaveCallback: function (settings, data) {
            delete data.search;
            localStorage.setItem(`DataTables_${settings.sInstance}_/tracker`, JSON.stringify(data));
        },
        stateLoadCallback: function (settings) {
            return JSON.parse(localStorage.getItem(`DataTables_${settings.sInstance}_/tracker`));
        },
        footerCallback: function (tfoot, data, start, end, display) {
            if (tfoot) {
                const activityData = this.api().column('lastActivity:name').data().toArray().filter(x => !isNaN(x));
                Array.from(tfoot?.children).find(td => td.classList.contains('last-activity')).innerText =
                    (activityData.length) ? secondsToHours(Math.min(...activityData)) : 'None';
            }
        },
        columnDefs: [
            {
                targets: 'last-activity',
                name: 'lastActivity'
            },
            {
                targets: 'hours',
                render: function (data, type, row) {
                    if (type === "sort" || type === 'type') {
                        if (data === "None")
                            return Number.MAX_VALUE;

                        return parseInt(data);
                    }
                    if (data === "None")
                        return data;

                    return secondsToHours(data);
                }
            },
            {
                targets: 'number',
                render: function (data, type, row) {
                    if (type === "sort" || type === 'type') {
                        return parseFloat(data);
                    }
                    return data;
                }
            },
            {
                targets: 'fraction',
                render: function (data, type, row) {
                    let splitted = data.split("/", 1);
                    let current = splitted[0]
                    if (type === "sort" || type === 'type') {
                        return parseInt(current);
                    }
                    return data;
                }
            },
        ],

        // DO NOT use the scrollX or scrollY options. They cause DataTables to split the thead from
        // the tbody and render two separate tables.
    });

    const searchBox = document.getElementById("search");
    searchBox.value = tables.search();
    searchBox.focus();
    searchBox.select();
    const doSearch = () => {
        tables.search(searchBox.value);
        tables.draw();
    };
    searchBox.addEventListener("keyup", doSearch);
    window.addEventListener("keydown", (event) => {
        if (!event.ctrlKey && !event.altKey && event.key.length === 1 && document.activeElement !== searchBox) {
            searchBox.focus();
            searchBox.select();
        }
        if (!event.ctrlKey && !event.altKey && !event.shiftKey && event.key === "Escape") {
            if (searchBox.value !== "") {
                searchBox.value = "";
                doSearch();
            }
            searchBox.blur();
            if (!document.getElementById("tables-container"))
                window.scroll(0, 0);
            event.preventDefault();
        }
    });
    const target_second = parseInt(document.getElementById('tracker-wrapper').getAttribute('data-second')) + 3;
    console.log("Target second of refresh: " + target_second);

    function getSleepTimeSeconds() {
        // -40 % 60 is -40, which is absolutely wrong and should burn
        var sleepSeconds = (((target_second - new Date().getSeconds()) % 60) + 60) % 60;
        return sleepSeconds || 60;
    }

    let update_on_view = false;
    const update = () => {
        if (document.hidden) {
            console.log("Document reporting as not visible, not updating Tracker...");
            update_on_view = true;
        } else {
            update_on_view = false;
            const target = $("<div></div>");
            console.log("Updating Tracker...");
            target.load(location.href, function (response, status) {
                if (status === "success") {
                    target.find(".table").each(function (i, new_table) {
                        const new_trs = $(new_table).find("tbody>tr");
                        const footer_tr = $(new_table).find("tfoot>tr");
                        const old_table = tables.eq(i);
                        const topscroll = $(old_table.settings()[0].nScrollBody).scrollTop();
                        const leftscroll = $(old_table.settings()[0].nScrollBody).scrollLeft();
                        old_table.clear();
                        if (footer_tr.length) {
                            $(old_table.table).find("tfoot").html(footer_tr);
                        }
                        old_table.rows.add(new_trs);
                        old_table.draw();
                        $(old_table.settings()[0].nScrollBody).scrollTop(topscroll);
                        $(old_table.settings()[0].nScrollBody).scrollLeft(leftscroll);
                    });
                    $("#multi-stream-link").replaceWith(target.find("#multi-stream-link"));
                } else {
                    console.log("Failed to connect to Server, in order to update Table Data.");
                    console.log(response);
                }
            })
        }
        updater = setTimeout(update, getSleepTimeSeconds() * 1000);
    }
    let updater = setTimeout(update, getSleepTimeSeconds() * 1000);

    window.addEventListener('resize', () => {
        adjustTableHeight();
        tables.draw();
    });

    window.addEventListener('visibilitychange', () => {
        if (!document.hidden && update_on_view) {
            console.log("Page became visible, tracker should be refreshed.");
            clearTimeout(updater);
            update();
        }
    });

    adjustTableHeight();
});
