import { action, computed, flow, observable, runInAction } from "mobx";

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

import { request } from "../utils/request.js";
import { locationRestQueueAutomaticHintDelete } from "../wp-api/queue-automatic-hint.delete.js";
import { locationRestQueueAutomaticPost } from "../wp-api/queue-automatic.post.js";
import { locationRestQueueQueueNoticeDelete } from "../wp-api/queue-notice.delete.js";

import type { RootStore } from "./stores.js";
import type { Handler } from "../models/handler.js";
import type { PausedError } from "../models/pausedError.js";
import type { QueueItem } from "../models/queueItem.js";
import type { ClassProperties } from "../utils/types.js";
import type {
    ParamsRestQueueAutomaticHintDelete,
    RequestRestQueueAutomaticHintDelete,
    ResponseRestQueueAutomaticHintDelete,
} from "../wp-api/queue-automatic-hint.delete.js";
import type {
    ParamsRestQueueAutomaticPost,
    RequestRestQueueAutomaticPost,
    ResponseRestQueueAutomaticPost,
} from "../wp-api/queue-automatic.post.js";
import type {
    ParamsRestQueueQueueNoticeDelete,
    RequestRestQueueQueueNoticeDelete,
    ResponseRestQueueQueueNoticeDelete,
} from "../wp-api/queue-notice.delete.js";

type CancellablePromise<R> = ReturnType<ReturnType<typeof flow<R, any>>>;

class OptionStore extends BaseOptions {
    @observable
    public view = {
        isAutomaticInfoPanelOpen: false,
    };

    // Implement "others" property in your Assets.php;
    @observable
    public others: {
        showLicenseFormImmediate: boolean;
        isDevLicense: boolean;
        licenseActivationLink: string;
        installPluginNonce: string;
        initialQueue: {
            rows: ClassProperties<QueueItem>[];
            count: number;
            estimate: string;
        };
        initialPausedError?: ClassProperties<PausedError>;
        manageOptions: string;
        seoAttachmentPage: string;
        countDown: {
            processing: number;
            pause: number;
        };
        handlers: ClassProperties<Handler>[];
        isAutomaticQueueing: boolean;
        isFirstTimeMoveHintDismissed: boolean;
        isFirstTimeQueueNoticeDismissed: boolean;
        supportsAllChildrenSql: boolean;
        pluginsUrl: string;
    };

    public readonly pureSlug: ReturnType<typeof BaseOptions.getPureSlug>;

    public readonly pureSlugCamelCased: ReturnType<typeof BaseOptions.getPureSlug>;

    public readonly rootStore: RootStore;

    public get isRatable() {
        return isRatable(this.slug);
    }

    @computed
    public get forcePopupOpen() {
        return (
            this.view.isAutomaticInfoPanelOpen ||
            (!this.others.isFirstTimeQueueNoticeDismissed && this.rootStore.queueStore.isHandlerActive)
        );
    }

    public constructor(rootStore: RootStore) {
        super();
        this.rootStore = rootStore;
        this.pureSlug = BaseOptions.getPureSlug(process.env.slug);
        this.pureSlugCamelCased = BaseOptions.getPureSlug(process.env.slug, true);

        // Use the localized WP object to fill this object values.
        runInAction(() => Object.assign(this, (window as any)[this.pureSlugCamelCased]));
    }

    @action
    public setAutomaticInfoPanelOpen(state: boolean) {
        this.view.isAutomaticInfoPanelOpen = state;

        // When the automatic queueing box is been viewed the first time, dismiss it
        if (!state && !this.others.isFirstTimeMoveHintDismissed) {
            this.others.isFirstTimeMoveHintDismissed = true;

            request<
                RequestRestQueueAutomaticHintDelete,
                ParamsRestQueueAutomaticHintDelete,
                ResponseRestQueueAutomaticHintDelete
            >({
                location: locationRestQueueAutomaticHintDelete,
            });
        }
    }

    public setIsAutomaticQueueing: (state: boolean) => CancellablePromise<void> = flow(function* (
        this: OptionStore,
        state,
    ) {
        yield request<RequestRestQueueAutomaticPost, ParamsRestQueueAutomaticPost, ResponseRestQueueAutomaticPost>({
            location: locationRestQueueAutomaticPost,
            request: {
                state,
            },
        });
        this.others.isAutomaticQueueing = state;
    });

    public dismissFirstTimeQueueNotice: () => CancellablePromise<void> = flow(function* (this: OptionStore) {
        // Already dismissed
        if (this.others.isFirstTimeQueueNoticeDismissed) {
            return;
        }

        this.others.isFirstTimeQueueNoticeDismissed = true;
        yield request<
            RequestRestQueueQueueNoticeDelete,
            ParamsRestQueueQueueNoticeDelete,
            ResponseRestQueueQueueNoticeDelete
        >({
            location: locationRestQueueQueueNoticeDelete,
        });
    });

    @action
    public setShowLicenseFormImmediate(state: boolean) {
        this.others.showLicenseFormImmediate = state;
    }
}

export { OptionStore };
