import { dispatchInitiatorExecution } from "./dispatchInitiatorExecution.js";
import { isCurrentlyInTransaction } from "../../checker/transaction.js";
import { OPT_IN_CONTENT_BLOCKER_ALL } from "../../events/optInContentBlockerAll.js";

import type { InitiatorJQueryReadyDetails } from "../../events/initiatorExecution.js";

let overwritten = false;

/**
 * Overwrite `jQuery(fn)` as they can not be triggered by our script blocker.
 *
 * @see https://api.jquery.com/ready/
 */
function applyJQueryReadyInitiator(doc: Document) {
    // Only overwrite once
    if (overwritten) {
        return;
    }

    const { jQuery } = (doc.defaultView || (doc as any).parentWindow) as any;

    if (!jQuery) {
        return;
    }

    const originalFn = jQuery.fn.ready;
    jQuery.fn.ready = function (fn: ($: any) => void) {
        if (fn) {
            // Redirect to own thread to avoid variable order lacks (e. g. Uncode Gmaps Integration, Contact Form 7
            const executeHandle = () =>
                setTimeout(() => {
                    const afterExecution = dispatchInitiatorExecution<InitiatorJQueryReadyDetails>({
                        type: "jQueryReady",
                        fn,
                    });
                    fn(jQuery);
                    afterExecution();
                }, 0);

            if (isCurrentlyInTransaction()) {
                // Standard behavior: jQuery.ready() got called with the unblocked script
                document.addEventListener(OPT_IN_CONTENT_BLOCKER_ALL, executeHandle, {
                    once: true,
                });
            } else {
                // Edge case: jQuery.ready() got called multiple times and nested
                // Example:
                // <script>
                // console.log("gravatar.com/avatar");
                // jQuery(function() {
                //   console.log("unblocked");
                //   jQuery(function() {
                //     console.log("unblocked 2");
                //   });
                // });
                // </script>
                executeHandle();
            }
        }
        return originalFn.apply(this, [
            () => {
                // Silence is golden.
            },
        ]);
    };

    overwritten = true;
}

export { applyJQueryReadyInitiator };
