import { consentSync } from "./consentSync.js";
import { OPT_IN_EVENT } from "../events/optIn.js";
import { OPT_OUT_EVENT } from "../events/optOut.js";

import type { OptInEvent } from "../events/optIn.js";
import type { OptOutEvent } from "../events/optOut.js";

/**
 * `window.consentApi.consent`: Check if a given technical information (e.g. HTTP Cookie, LocalStorage, ...) has a consent:
 *
 * - When a technical information exists in defined cookies, the Promise is only resolved after given consent
 * - When no technical information exists, the Promise is immediate resolved
 *
 * Example (ES5):
 * ```js
 * (window.consentApi && window.consentApi.consent("http", "_twitter_sess", ".twitter.com") || Promise.resolve()).then(function() {
 *     console.log("Consent for Twitter embed given, do something...!");
 * });
 * ```
 *
 * Example (ES6, TS):
 * ```js
 * (window.consentApi?.consent("http", "_twitter_sess", ".twitter.com") || Promise.resolve()).then(() => {
 *     console.log("Consent for Twitter embed given, do something...!");
 * });
 * ```
 *
 * **Since 2.3.0**: You can also check for consent by cookie ID (ID in `wp_posts`, post id):
 *
 * ```js
 * window.consentApi.consent(15)
 * ```
 *
 * **Since 3.4.14**: You can also check for consent by service unique name:
 *
 * ```js
 * window.consentApi.consent("google-analytics-ua")
 * ```
 */
function consent(...args: Parameters<typeof consentSync>) {
    return new Promise<ReturnType<typeof consentSync>>((resolve, reject) => {
        const result = consentSync(...args);
        const { cookie: foundCookie, consentGiven, cookieOptIn } = result;

        if (foundCookie) {
            if (consentGiven) {
                if (cookieOptIn) {
                    resolve(result);
                } else {
                    reject(result);
                }
            } else {
                // Wait for consent
                document.addEventListener(OPT_IN_EVENT, (async ({ detail: { service } }: CustomEvent<OptInEvent>) => {
                    if (service === foundCookie) {
                        resolve(result);
                    }
                }) as any);

                // Wait for opt out
                document.addEventListener(OPT_OUT_EVENT, (async ({ detail: { service } }: CustomEvent<OptOutEvent>) => {
                    if (service === foundCookie) {
                        reject(result);
                    }
                }) as any);
            }
        } else {
            resolve(result);
        }
    });
}

export { consent };
