var filtersTable;
    filterOptions = null;

// Create filters table
async function initFiltersTable() {
    filterOptions = await getFilterOptions();
    await initTable("#filtersTabPane", "filtersTable", loadFilters, showEditFilterModal, deleteSelectedFilters, filterOptions);

    filtersTable = $("#filtersTable").DataTable({
        info: false,
        paging: false,
        ordering: false,
        searching: false,
        autoWidth: false,
        order: [],
        select: {
            style: "multi+shift",
            selector: 'th:first-child input[type="checkbox"]'
        },
        columnDefs: [
            { orderable: false, targets: "no-sort" },
            {
                targets: 0,
                checkboxes: { selectRow: true }
            }
        ],
        columns: [
            {
                // Select row checkbox column
                title: '<input type="checkbox" class="form-check-input table-select-all" />',
                data: null,
                orderable: false,
                className: "text-center col-switch-width",
                render: function() {
                    return '<input type="checkbox" class="form-check-input table-select-row" />'
                }
            },
            { title: "ID", data: "id", visible: false },
            {
                title: "Name",
                data: "name",
                render: function(data, type, row) {
                    return `<button type="button" onclick="showEditFilterModal(${row.id})" class="btn btn-link text-start text-decoration-none">${data}</button>`
                }
            },
            {
                title: "Matching Algorithm",
                data: "matching_algorithm",
                render: function(data) {
                    switch (data) {
                        case 1: return "Any Word";
                        case 2: return "All Words";
                        case 3: return "Exact Match";
                        case 4: return "Regular Expression";
                        case 5: return "Fuzzy Match";
                        default:
                            console.error(`unknown matching algorithm '${data}'`);
                            return data;
                    }
                }
            },
            {
                title: "Match",
                data: "match"
            },
            {
                title: "Case Sensitivity",
                data: "is_insensitive",
                render: function(data) {
                    return data ? "Insensitive" : "Sensitive"
                }
            },
            {
                title: "Control List",
                data: "is_whitelist",
                render: function(data) {
                    return data ? "Whitelist" : "Blacklist";
                }
            }
        ]
    });

    bindTableCheckboxes("#filtersTable", filtersTable, "#filtersTabPane .table-del-btn");
}

$("#addFilterBtn").on("click", async function() {
    await showEditFilterModal(-1);
})

async function showEditFilterModal(filterId) {

    if (filterId === -1) {
        $("#filterFormModal input, #filterFormModal textarea").val("");
        $("#filterFormModal input:checkbox").prop("checked", false);

        $("#filterAlgorithm").val("").change();

        $("#filterFormModal .form-create").show();
        $("#filterFormModal .form-edit").hide();
    }
    else {
        const filter = filtersTable.row(function(idx, data, node) {
            return data.id === filterId;
        }).data();

        $("#filterAlgorithm").val("").change();
        $("#filterAlgorithm").val(filter.matching_algorithm).change();

        $("#filterName").val(filter.name);
        $("#filterMatch").val(filter.match);
        $("#filterWhitelist").prop("checked", filter.is_whitelist);
        $("#filterInsensitive").prop("checked", filter.is_insensitive);

        $("#filterFormModal .form-create").hide();
        $("#filterFormModal .form-edit").show();
    }

    $("#filterId").val(filterId);
    $("#filterFormModal").modal("show");
}

$("#filterForm").on("submit", async function(event) {
    event.preventDefault();

    var id = $("#filterId").val();
        name = $("#filterName").val();
        algorithm = $("#filterAlgorithm option:selected").val();
        match = $("#filterMatch").val();
        isWhitelist = $("#filterWhitelist").prop("checked");
        isInsensitive = $("#filterInsensitive").prop("checked");
        guildId = getCurrentlyActiveServer().guild_id;

    var filterPrimaryKey = await saveFilter(id, name, algorithm, match, isWhitelist, isInsensitive, guildId);

    if (filterPrimaryKey) {
        showToast("success", "Filter Saved", "Filter ID " + filterPrimaryKey);
        await loadFilters(guildId);
        await loadFilterOptions(guildId);
    }

    $("#filterFormModal").modal("hide");
});

async function saveFilter(id, name, algorithm, match, isWhitelist, isInsensitive, guildId) {
    var formData = new FormData();
    formData.append("name", name);
    formData.append("matching_algorithm", algorithm);
    formData.append("match", match);
    formData.append("is_whitelist", isWhitelist);
    formData.append("is_insensitive", isInsensitive);
    formData.append("guild_id", guildId);

    var response;

    try {
        if (id === "-1") response = await newFilter(formData);
        else response = await editFilter(id, formData);
    }
    catch (err) {
        showToast("danger", "Filter Error", err.responseText, 18000);
        return false
    }

    return response.id;
}

function clearExistingFilterRows() {
    $("#filtersTable thead .table-select-all").prop("checked", false).prop("indeterminate", false)
    filtersTable.clear().draw(false)
}

$("#filtersTabPane").on("click", ".table-refresh-btn", async function() {
    loadFilters(getCurrentlyActiveServer().guild_id);
});

async function loadFilters(guildId) {
    if (!guildId)
        return;

    setTableFilter("filtersTable", "guild_id", guildId);
    ensureTablePagination("filtersTable");

    $("#filtersTabPane .table-del-btn").prop("disabled", true);
    clearExistingFilterRows();

    try {
        var contentFilters = await getFilters(tableFilters["filtersTable"], tableSorts["filtersTable"]);
        filtersTable.rows.add(contentFilters.results).draw(false);
    }
    catch (err) {
        console.error(err)
        showToast("danger", `Error Loading Filters: HTTP ${err.status}`, err, 15000);
        return;
    }

    updateTableContainer(
        "filtersTabPane",
        tableFilters["filtersTable"]["page"],
        tableFilters["filtersTable"]["page_size"],
        contentFilters.results.length,
        contentFilters.count,
        contentFilters.next,
        contentFilters.previous
    );

    $("#filtersTable thead .table-select-all").prop("disabled", contentFilters.results.length === 0);
    console.debug(`loaded filters, ${contentFilters.results.length} found`);
}

$(document).ready(async function() {
    await loadMatchingAlgorithms();
});

async function loadMatchingAlgorithms() {
    // Disable input while options are loading
    $("#filterAlgorithm").prop("disabled", true);

    // Delete existing options
    $("#filterAlgorithm option").each(function() {
        if ($(this).val())
            $(this).remove();
    });

    // Clear select2 input
    $("#filterAlgorithm").val("").change();

    try {
        options = await getFilterOptions();
        options.actions.POST.matching_algorithm.choices.forEach(algorithm => {
            $("#filterAlgorithm").append($("<option>", {
                text: algorithm.display_name,
                value: algorithm.value > 0 ? algorithm.value : ""  // empty string for 'None' option at 0
            }));                                                   // (helps with validation)
        });
    }
    catch (error) {
        console.error(error);
    }
    finally {
        // Re-enable the input
        $("#filterAlgorithm").prop("disabled", false);
    }
};

$(document).on("selectedServerChange", async function() {
    const activeServer = getCurrentlyActiveServer();
    await loadFilters(activeServer.guild_id);
});

// #region Delete Filters

$("#deleteEditFilter").on("click", async function() {
    const filterId = parseInt($("#filterId").val());
    const filter = filtersTable.row(function(idx, row) { return row.id === filterId }).data();

    $("#filterFormModal").modal("hide");

    await confirmDeleteModal(
        "Confirm Deletion",
        `Do you wish to permanently delete <b>${filter.name}</b>?`,
        async () => {
            await deleteFilter(filterId);
            await loadFilters(getCurrentlyActiveServer().guild_id);

            showToast(
                "danger",
                "Deleted a Filter",
                filter.name,
                12000
            );
        },
        async () => {
            $("#filterFormModal").modal("show");
        }
    );
});

async function deleteSelectedFilters() {
    const rows = filtersTable.rows(".selected").data().toArray();
    const names = rows.map(row => row.name);
    const namesString = arrayToHtmlList(names, true).prop("outerHTML");
    const multiple = names.length > 1;

    await confirmDeleteModal(
        `Confirm ${multiple ? "Multiple Deletions" : "Deletion"}`,
        `Do you wish to permanently delete ${multiple ? "these" : "this"} <b>${names.length}</b> filter${multiple ? "s" : ""}?<br><br>${namesString}`,
        async () => {
            rows.forEach(async row => { await deleteFilter(row.id) });

            showToast(
                "danger",
                `Delete ${names.length} Subscription${multiple ? "s" : ""}`,
                `${arrayToHtmlList(names, false).prop("outerHTML")}`,
                12000
            );

            await loadFilters(getCurrentlyActiveServer().guild_id);
        },
        null
    );
}

// #endregion
