// import $ from "jquery"; // not always available
import { HTML_ATTRIBUTE_COOKIE_IDS, HTML_ATTRIBUTE_JQUERY_HIJACK_EACH } from "./htmlAttributes.js";
import { OPT_IN_CONTENT_BLOCKER_ALL } from "../events/optInContentBlockerAll.js";

const ALREADY_OVERWRITTEN_PROPERTY = "hijackQueryEach";

/**
 * Allows to delay `.each` calls on jQuery elements.
 *
 * Example when `div[block-me]` is blocked:
 *
 * ```html
 * <div block-me="1" class="my-test">blocked</div>
 * <div class="my-test">not blocked</div>
 * <script>
 * jQuery(() => {
 *  jQuery(".my-test").each((index, element) => {
 *    console.log(index, jQuery(element).html());
 *  });
 * });
 * </script>
 * ```
 *
 * @see https://api.jquery.com/each/
 */
function hijackJqueryEach(selectors: string[]) {
    const $ = (window as any).jQuery;

    if (!$?.each || $[ALREADY_OVERWRITTEN_PROPERTY]) {
        return;
    }
    $[ALREADY_OVERWRITTEN_PROPERTY] = true;

    const originalFunction = $.each;
    $.each = (array: any[], callback: (...args: any[]) => void) =>
        originalFunction.apply($, [
            array,
            function (this: any, index: number, element: any) {
                if (
                    element instanceof HTMLElement &&
                    element.hasAttribute(HTML_ATTRIBUTE_COOKIE_IDS) &&
                    (element.hasAttribute(HTML_ATTRIBUTE_JQUERY_HIJACK_EACH) || element.matches(selectors.join(",")))
                ) {
                    // Wait for consent and afterwards, execute the command
                    element.addEventListener(OPT_IN_CONTENT_BLOCKER_ALL, () => callback.apply(this, [index, element]));
                    return undefined;
                }
                return callback.apply(this, [index, element]);
            },
        ]);
}

export { hijackJqueryEach };
