import $ from "jquery";

import { RatingPointer } from "@devowl-wp/real-utils";

import { RootStore } from "../../store/stores.js";

class MakeSortable {
    public readonly $tbody: JQuery<HTMLElement>;

    /* v8 ignore next 4 */
    public constructor($tbody: MakeSortable["$tbody"]) {
        this.$tbody = $tbody;
        this.init();
    }

    public helper(this: JQueryUI.SortableOptions, e: JQueryEventObject, ui: JQueryUI.Sortable) {
        const item = ui as unknown as JQuery<HTMLElement>;

        // Fix width to keep column width
        item.children()
            .children()
            .each(function () {
                $(this).width($(this).width());
            });

        // Store current height
        item.data("sortableHeight", item.height());

        return ui as unknown as Element;
    }

    public start(this: MakeSortable, e: JQueryEventObject, ui: JQueryUI.SortableUIParams) {
        ui.placeholder.height(ui.item.data("sortableHeight"));

        // Avoid breaking the table-header layout
        ui.placeholder.css("display", "table");
        ui.helper.css("display", "table");

        // Try to close the first-time-pointer
        try {
            const $pointer = this.$tbody.children(".rcpo-force-handler").find(".rcpo-handler");
            ($pointer as any).pointer("close").pointer("destroy");
            /* v8 ignore next 3 */
        } catch (e) {
            // Silence is golden.
        }
    }

    public stop(this: JQueryUI.SortableOptions, e: JQueryEventObject, ui: JQueryUI.SortableUIParams) {
        ui.placeholder.height("auto");
        ui.item.css("display", "table-row");
    }

    public async update(this: JQueryUI.SortableOptions, e: JQueryEventObject, ui: JQueryUI.SortableUIParams) {
        const sequence = $(this)
            .sortable("toArray")
            .map((item) => +item.substr(5));
        ui.item.addClass("updating-sequence rcpo-force-handler");
        ui.item.css("display", "table-row");

        try {
            await RootStore.get.postsStore.updateBySequence(sequence);
            const {
                optionStore: { isRatable, slug },
            } = RootStore.get;
            isRatable && new RatingPointer(slug, ui.item);
        } finally {
            ui.item.removeClass("updating-sequence rcpo-force-handler");
        }
    }

    private init() {
        !this.$tbody.data("uiSortable") &&
            this.$tbody.sortable({
                forceHelperSize: true,
                forcePlaceholderSize: true,
                items: "tr:not(.no-items)",
                axis: "y",
                handle: ".rcpo-handler",
                helper: this.helper,
                start: this.start.bind(this),
                stop: this.stop,
                update: this.update,
            });
    }
}

export { MakeSortable };
