$(document).ready(async function() {
    await initSubscriptionTable();
    await initFiltersTable();
    await initContentTable();

    $("#subscriptionsTab").click();

    await loadSavedGuilds();
    await loadServerOptions();
});

$(document).on("selectedServerChange", function() {
    $("#subscriptionsTab").click();
});

function genHexString(len=6) {
    let output = '';
    for (let i = 0; i < len; ++i) {
        output += (Math.floor(Math.random() * 16)).toString(16);
    }
    return output;
}

// my clone of python's datetime.strftime
function formatStringDate(date, format) {
    const padZero = (num, len) => String(num).padStart(len, "0");
    const abbreviate = (str) => str.slice(0, 3);
    const ordSuffix = day => (day % 100 >= 11 && day % 100 <= 13) ? "th" : ["th", "st", "nd", "rd"][day % 10] || "th";

    const formatters = {
        "%a": date => abbreviate(date.toLocaleString("en-GB", { weekday: "short" })),
        "%A": date => date.toLocaleString("en-GB", { weekday: "long" }),
        "%w": date => date.getDay(),
        "%d": date => padZero(date.getDate(), 2),
        "%-d": date => date.getDate(),
        "%b": date => abbreviate(date.toLocaleString("en-GB", { month: "short" })),
        "%B": date => date.toLocaleString("en-GB", { month: "long" }),
        "%m": date => padZero(date.getMonth() + 1, 2),
        "%-m": date => date.getMonth() + 1,
        "%y": date => padZero(date.getFullYear() % 100, 2),
        "%-y": date => date.getFullYear() % 100,
        "%Y": date => date.getFullYear(),
        "%H": date => padZero(date.getHours(), 2),
        "%-H": date => date.getHours(),
        "%I": date => padZero(date.getHours() % 12 || 12, 2),
        "%-I": date => date.getHours() % 12 || 12,
        "%p": date => date.getHours() >= 12 ? "PM" : "AM",
        "%M": date => padZero(date.getMinutes(), 2),
        "%-M": date => date.getMinutes(),
        "%S": date => padZero(date.getSeconds(), 2),
        "%-S": date => date.getSeconds(),
        "%f": date => padZero(date.getMilliseconds() * 1000, 6),
        "%z": date => {
            const offset = date.getTimezoneOffset();
            const sign = offset > 0 ? "-" : "+";
            const absOffset = Math.abs(offset);
            const hours = padZero(Math.floor(absOffset / 60), 2);
            const minutes = padZero(absOffset % 60, 2);
            return `${sign}${hours}${minutes}`;
        },
        "%Z": date => {
            const match = date.toTimeString().match(/\((.*)\)/);
            return match ? match[1] : "";
        },
        "%j": date => padZero(Math.ceil((date - new Date(date.getFullYear(), 0, 1)) / 86400000) + 1, 3),
        "%-j": date => Math.ceil((date - new Date(date.getFullYear(), 0, 1)) / 86400000) + 1,
        "%U": date => padZero(Math.floor((date - new Date(date.getFullYear(), 0, 1) + (86400000 * (date.getDay() || 7 - 1))) / (86400000 * 7)), 2),
        "%W": date => padZero(Math.floor((date - new Date(date.getFullYear(), 0, 1) + (86400000 * (date.getDay() || 7))) / (86400000 * 7)), 2),
        "%c": date => date.toLocaleString(),
        "%x": date => date.toLocaleDateString(),
        "%X": date => date.toLocaleTimeString(),
        "%D": date => date.getDate() + ordSuffix(date.getDate()),        
        "%%": () => "%"
    };

    return format.replace(/%[a-zA-Z%-]/g, match => formatters[match] ? formatters[match](date) : match);
}

// #region Colour Controls
$(".colour-control-picker").on("change", function() {
    $(this).closest(".colour-control-group").find(".colour-control-text").val($(this).val());
});

$(".colour-control-text").on("change", function() {
    $(this).closest(".colour-control-group").find(".colour-control-picker").val($(this).val());
});

function updateColourInput(id, hexString) {
    hexString = normaliseHexString(hexString.toUpperCase());
    $(`#${id} .colour-picker`).val(hexString);
    $(`#${id} .colour-text`).val(hexString);
}

function getColourInputVal(id, includeHashtag=true) {
    const hexString = $(`#${id}Text`).val();
    return normaliseHexString(hexString, includeHashtag);
}

function normaliseHexString(hexString, includeHashtag=true) {
    console.debug(`normalising hex string '${hexString}' include hashtag '${includeHashtag}'`);

    // Remove any non-hex characters (e.g., additional hashtags)
    hexString = hexString.replace(/[^A-F0-9]/gi, '');

    // Ensure the hex string has a valid length of either 3, 6, or 8 characters
    if (![3, 6, 8].includes(hexString.length)) {
        throw new Error(`Invalid hex string length. Must be 3, 6, or 8 characters. hexString=${hexString}`);
    }

    return includeHashtag ? `#${hexString}` : hexString;
}

$(document).ready(function() {
    $(".colour-input").each(function() {
        let id = $(this).attr("data-id")
            label = $(this).attr("data-label");
            helpText = $(this).attr("data-helptext");
            tabIndex = parseInt($(this).attr("data-tabindex"));
            defaultColour = $(this).attr("data-defaultcolour");
            defaultColour = defaultColour ? defaultColour : "#3498db"

        $(this).replaceWith(`
            <label for="${id}Picker" class="form-label">${label}</label>
            <div id="${id}" class="input-group">
                <input type="color" name="${id}Picker" id="${id}Picker" class="form-control-color input-group-text colour-picker" tabindex="${tabIndex}">
                <input type="text" name="${id}Text" id="${id}Text" class="form-control colour-text" tabindex="${tabIndex + 1}">
                <button type="button" class="btn btn-secondary colour-reset" data-bs-toggle="tooltip" data-bs-title="Reset Colour" data-defaultcolour="${defaultColour}" tabindex="${tabIndex + 2}">
                    <i class="bi bi-arrow-clockwise"></i>
                </button>
                <button type="button" class="btn btn-secondary colour-random" data-bs-toggle="tooltip" data-bs-title="Random Colour" tabindex="${tabIndex + 3}">
                    <i class="bi bi-dice-5"></i>
                </button>
            </div>
            <div class="form-text">${helpText}</div>
        `);

        $(`#${id} .colour-picker`).on("change", function() {
            updateColourInput(id, $(this).val());
        });

        $(`#${id} .colour-text`).on("change", function() {
            updateColourInput(id, $(this).val());
        });

        $(`#${id} .colour-reset`).on("click", function() {
            updateColourInput(id, $(this).attr("data-defaultcolour"));
        });

        $(`#${id} .colour-random`).on("click", function() {
            updateColourInput(id, "#" + genHexString(6));
        });

        updateColourInput(id, "#" + defaultColour)
        $(`#${id} [data-bs-toggle="tooltip"]`).tooltip();
    });
});

async function confirmDeleteModal(title, description, acceptFunc, declineFunc) {
    let $modal = $("#confirmDeleteModal");
    $modal.find(".modal-title").text(title);
    $modal.find(".modal-body > p").html(description);
    $modal.find(".confirm-delete-btn").off("click").on("click", async function(e) {
        await acceptFunc()
        $modal.modal("hide");
    });
    $modal.find(".dismiss-delete-btn").off("click").on("click", async function(e) {
        if (declineFunc) await declineFunc();
        $modal.modal("hide");
    });
    $modal.modal("show");
}

function arrayToHtmlList(array, bold=false) {
    $ul = $("<ul>");

    array.forEach(item => {
        let $li = $("<li>");
        $ul.append(bold ? $li.append($("<b>").text(item)) : $li.text(item));
    });

    return $ul;
}