var filtersTable;

// Create filters table
async function initFiltersTable() {
    await initTable("#filtersTabPane", "filtersTable", loadFilters);

    filtersTable = $("#filtersTable").DataTable({
        info: false,
        paging: 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 `<a href="#" onclick="showEditFilterModal(${row.id})" class="text-decoration-none">${data}</a>`
                }
            },
            {
                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, "#deleteSelectedFiltersBtn");
}

$("#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)
}

$("#refreshFilterBtn").on("click", async function() {
    loadFilters(getCurrentlyActiveServer().guild_id);
});

async function loadFilters(guildId, page=1, pageSize=null) {

    if (!guildId)
        return;

    if (!pageSize)
        pageSize = $("#filtersTablePageSize").val();

    $("#deleteSelectedFiltersBtn").prop("disabled", true);
    clearExistingFilterRows();

    try {
        const filters = await getFilters(guildId);
        filtersTable.rows.add(filters.results).draw(false);

        updateTablePagination("#filtersTabPane .table-pagination", page, pageSize, filters.count, filters.next, filters.previous);
        updateTablePaginationInfo("#filtersTabPane .table-page-info", filters.results.length, filters.count);

        $("#filtersTable thead .table-select-all").prop("disabled", filters.results.length === 0);
    }
    catch (err) {
        console.error(err)
        console.error(JSON.stringify(err, null, 4));
        showToast("danger", `Error Loading Filters: HTTP ${err.status}`, err.responseJSON.message, 15000);
    }
}

$(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);
});

$("#deleteSelectedFiltersBtn").on("click", async function() {

    var rows = filtersTable.rows(".selected").data();
    $.each(rows, async function() {
        await deleteFilter(this.id);
        showToast("danger", "Deleted Filter", "Filter ID: " + this.id)
    })

    setTimeout(async () => {
        const guildId = getCurrentlyActiveServer().guild_id;
        await loadFilters(guildId);
        loadFilterOptions(guildId);
    }, 500)
})

$("#deleteEditFilter").on("click", async function() {
    const filterId = $("#filterId").val();
    await deleteFilter(filterId);
    await loadFilters(getCurrentlyActiveServer().guild_id);
    $("#filterFormModal").modal("hide");
    showToast("danger", "Deleted Filter", "Filter ID: " + filterId);
});