import { computed, flow } from "mobx";

import { AbstractPostCollection, ClientCollection, RouteHttpVerb } from "@devowl-wp/utils";

import { BannerLinkModel } from "./bannerLinkModel.js";
import { request } from "../utils/request.js";
import { locationRestBannerLinksOrderPut } from "../wp-api/bannerLinksOrder.put.js";

import type { OptionStore } from "../store/option.js";
import type {
    ParamsRouteBannerLinksOrderPut,
    RequestRouteBannerLinksOrderPut,
    ResponseRouteBannerLinksOrderPut,
} from "../wp-api/bannerLinksOrder.put.js";

@ClientCollection.annotate({
    path: "/rcb-banner-link",
    singlePath: "/rcb-banner-link/:id",
    namespace: "wp/v2",
    methods: [RouteHttpVerb.GET],
    request,
})
class BannerLinkCollection extends AbstractPostCollection<BannerLinkModel> {
    public readonly store: OptionStore;

    @computed
    public get sortedBannerLinks() {
        const result = Array.from(this.entries.values());
        result.sort((a, b) => {
            if (a.data.menu_order < b.data.menu_order) {
                return -1;
            } else if (a.data.menu_order > b.data.menu_order) {
                return 1;
            } else {
                // a.menu_order === b.menu_order
                if (a.key < b.key) {
                    return 1;
                } else if (a.key > b.key) {
                    return -1;
                } else {
                    return 0;
                }
            }
        });
        return result;
    }

    public orderCookies: (ids: number[]) => Promise<void> = flow(function* (this: BannerLinkCollection, ids) {
        this.busy = true;
        try {
            yield request<
                RequestRouteBannerLinksOrderPut,
                ParamsRouteBannerLinksOrderPut,
                ResponseRouteBannerLinksOrderPut
            >({
                location: locationRestBannerLinksOrderPut,
                request: {
                    ids,
                },
            });

            // Apply the order to existing cached models instead of fetching again
            let i = 0;
            for (const id of ids) {
                const cookie = this.entries.get(id);
                cookie.setOrder(i);
                i++;
            }
        } catch (e) {
            console.log(e);
            throw e;
        } finally {
            this.busy = false;
        }
    });

    public constructor(store: OptionStore) {
        super();
        this.store = store;
    }

    public instance(response: BannerLinkModel["data"]): BannerLinkModel {
        return new BannerLinkModel(this).fromResponse(response);
    }
}

export { BannerLinkCollection };
