/**
 * Hijacks the custom elements to ensure that HTML5 web components are properly loaded.
 *
 * This function addresses the issue where multiple HTML5 web components cannot be rendered sporadically due to missing HTML attributes
 * and undefined properties. It ensures that the lifecycle of the HTML5 web components is correctly managed by overriding the necessary
 * lifecycle callbacks.
 *
 * Call this function early in your script to hijack the custom elements.
 *
 * As `unblockMechanism` you can pass `window.consentApi.unblock` with the `callback` option to keep sync behavior.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks
 * @see https://stackoverflow.com/questions/55772668/how-to-override-connectedcallback-and-other-functions-for-every-element-on-a-pag#comment98237900_55772668
 * @see https://stackoverflow.com/questions/40492330/difference-between-constructor-and-connectedcallback-in-custom-elements-v1
 */
function hijackWebComponents(unblockMechanism: (element: HTMLElement, run: () => void) => void) {
    const originalDefine = window.customElements.define;
    window.customElements.define = function (...args) {
        const [, constructor] = args;
        const originalConnectedCallback = constructor?.prototype?.connectedCallback;
        if (originalConnectedCallback) {
            constructor.prototype.connectedCallback = function () {
                unblockMechanism(this, () => {
                    originalConnectedCallback.call(this);
                });
            };
        }
        return originalDefine.apply(this, args);
    };
}

export { hijackWebComponents };
