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

import { ChecklistStore } from "./checklist.js";
import { ConsentStore } from "./consent.js";
import { CookieStore } from "./cookie.js";
import { CustomizeBannerStore } from "./customizeBanner.js";
import { OptionStore } from "./option.js";
import { ScannerStore } from "./scanner.js";
import { StatsStore } from "./stats.js";
import { TcfStore } from "./tcf.js";

import type { Context, FC, PropsWithChildren } from "react";

/**
 * A collection of all available stores which gets available
 * through the custom hook useStores in your function components.
 *
 * @see https://mobx.js.org/best/store.html#combining-multiple-stores
 */
class RootStore {
    private static me: RootStore;

    public optionStore: OptionStore;

    public customizeBannerStore: CustomizeBannerStore;

    public cookieStore: CookieStore;

    public consentStore: ConsentStore;

    public statsStore: StatsStore;

    public checklistStore: ChecklistStore;

    public tcfStore: TcfStore;

    public scannerStore: ScannerStore;

    private contextMemo: {
        StoreContext: Context<RootStore>;
        StoreProvider: FC<PropsWithChildren>;
        useStores: () => RootStore;
    };

    public get context() {
        return this.contextMemo
            ? this.contextMemo
            : (this.contextMemo = createContextFactory(this as unknown as RootStore));
    }

    private constructor() {
        this.optionStore = new OptionStore(this);
        this.customizeBannerStore = new CustomizeBannerStore(this);
        this.cookieStore = new CookieStore(this);
        this.consentStore = new ConsentStore(this);
        this.statsStore = new StatsStore(this);
        this.checklistStore = new ChecklistStore(this);
        this.tcfStore = new TcfStore(this);
        this.scannerStore = new ScannerStore(this);
    }

    public static get StoreProvider() {
        return RootStore.get.context.StoreProvider;
    }

    public static get get() {
        return RootStore.me ? RootStore.me : (RootStore.me = new RootStore());
    }
}

const useStores = () => RootStore.get.context.useStores();

export { RootStore, useStores };
