import { executeClientJob } from "./executor.js";
import { JOB_DONE_EVENT_PREFIX } from "../../types/events/jobDone.js";
import { REMAINING_EVENT } from "../../types/events/remaining.js";
import { getStaticOptions } from "../../utils/options.js";
import { jobDelay } from "../job/delay.js";

import type { JobDoneEvent } from "../../types/events/jobDone.js";
import type { RemainingEvent } from "../../types/events/remaining.js";
import type { Job } from "../../types/job.js";
import type { getGlobalQueue } from "../global.js";
import type { Task } from "../queueClass.js";

/**
 * Convert a client job to promise.
 */
function convertClientJobToPromise(queue: ReturnType<typeof getGlobalQueue>, job: Job) {
    const { type } = job;

    const fn: Task = async () => {
        const updateRemaining = () => {
            const { remaining } = getStaticOptions();
            if (remaining[type]) {
                remaining[type][0] -= 1;
            }

            document.dispatchEvent(
                new CustomEvent<RemainingEvent>(REMAINING_EVENT, {
                    detail: {
                        remaining,
                    },
                }),
            );
        };

        try {
            const success = await executeClientJob(job);
            updateRemaining();

            document.dispatchEvent(
                new CustomEvent<JobDoneEvent>(`${JOB_DONE_EVENT_PREFIX}${type}`, {
                    detail: {
                        job,
                        success,
                    },
                }),
            );
        } catch (e) {
            // Something went wrong between request and executor - we pause the queue here cause
            // we wait for the next refresh of the page.
            queue.handler.pause();
        }
    };

    const delay: Task = () => jobDelay(job);

    return [fn, delay];
}

export { convertClientJobToPromise };
