var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
import React from 'react';
import ReactDOM from 'react-dom';
import * as arComponents from '@r2u/react-ar-components';
import state from '../state';
import { getActionAlreadySeen, getScreenAlreadyOpened, setActionAlreadySeen, setScreenAlreadyOpened, } from '../services/cookies';
import product from '../services/product';
import * as analytics from '../services/analytics';
import { get } from '../services/requests';
import Fallback from '../screens/Fallback';
import InstructionsScreen from '../screens/Instructions';
import FeedbackScreen from '../screens/Feedback';
import SocialScreen from '../screens/Social';
import GrowthBook from '@growthbook/growthbook';
import { IS_ANDROID, IS_IOS } from '../services/constants';
const isIOSInAppBrowser = () => IS_IOS && /instagram|FBAN|FBAV|LinkedInApp/i.test(navigator.userAgent);
const HASH_FALLBACK = '#no-ar-fallback';
const createFallbackScreen = ({ glb, fallbackOptions, }) => {
    const root = document.createElement('div');
    const rootEvent = 'r2u-open-fallback';
    document.body.appendChild(root);
    const render = (props) => {
        ReactDOM.render(React.createElement(Fallback, Object.assign({ openerElement: root, openerEvent: rootEvent, fallbackOptions: fallbackOptions }, props)), root);
    };
    render({ glb });
    return {
        open: () => {
            root.dispatchEvent(new Event(rootEvent));
        },
        render,
    };
};
const createInstructionsScreen = (_a) => {
    var { hasWaterMark, onOpen, activateAR, sku } = _a, arProps = __rest(_a, ["hasWaterMark", "onOpen", "activateAR", "sku"]);
    const root = document.createElement('div');
    const rootEvent = 'r2u-open-instructions';
    document.body.appendChild(root);
    const render = (props) => {
        ReactDOM.render(React.createElement(InstructionsScreen, Object.assign({ openerElement: root, openerEvent: rootEvent, onOpen: onOpen, hasWaterMark: hasWaterMark, activateAR: activateAR, customerId: state.customer._id, sku: sku }, props)), root);
    };
    render(arProps);
    return {
        open: () => {
            root.dispatchEvent(new Event(rootEvent));
        },
        render,
    };
};
const createSocialFallbackScreen = () => {
    const root = document.createElement('div');
    const rootEvent = 'r2u-open-social-fallback';
    document.body.appendChild(root);
    ReactDOM.render(React.createElement(SocialScreen, { openerElement: root, openerEvent: rootEvent }), root);
    return {
        open: () => {
            root.dispatchEvent(new Event(rootEvent));
        },
        render: () => undefined,
    };
};
const createFeedbackScreen = (_a) => {
    var { container } = _a, feedbackProps = __rest(_a, ["container"]);
    const openerEvent = 'r2u-feedback-open';
    const root = document.createElement('div');
    root.className = 'feedback';
    container.appendChild(root);
    ReactDOM.render(React.createElement(FeedbackScreen, Object.assign({ openerElement: root, openerEvent: openerEvent }, feedbackProps)), root);
    return {
        open: () => {
            root.dispatchEvent(new Event(openerEvent));
        },
        render: () => undefined,
    };
};
function open({ element, event = 'click' }) {
    return __awaiter(this, void 0, void 0, function* () {
        element.dispatchEvent(new Event(event));
    });
}
const alertMessage = 'Sentimos muito, mas infelizmente seu dispositivo não é compatível com a visualização em Realidade Aumentada';
const attachWebXREventListeners = (Events) => {
    analytics.webXR.setSession();
    // WebXR Session Start
    document.addEventListener(Events.r2uWebxrSessionStart, analytics.webXR.onSessionStart, { once: true });
    // WebXR Session End
    document.addEventListener(Events.r2uWebxrSessionEnd, analytics.webXR.onSessionEnd, { once: true });
    // WebXR Compatibility
    document.addEventListener(Events.r2uWebxrCompatible, () => analytics.webXR.setCompatible(true), { once: true });
    document.addEventListener(Events.r2uWebxrNotCompatible, () => analytics.webXR.setCompatible(false), { once: true });
    // Session events
    document.addEventListener(Events.r2uWebxrPlaneMapped, analytics.webXR.setPlaneMapped, { once: true });
    document.addEventListener(Events.r2uWebxrObjectPlaced, analytics.webXR.setObjectPlaced, { once: true });
    document.addEventListener(Events.r2uWebxrShowTranslatingInstructions, () => {
        analytics.webXR.setTranslateInstructions();
        setActionAlreadySeen('translate');
    }, { once: true });
    document.addEventListener(Events.r2uWebxrShowRotatingInstructions, () => {
        analytics.webXR.setRotateInstructions();
        setActionAlreadySeen('rotate');
    }, { once: true });
    document.addEventListener(Events.r2uWebxrTranslating, () => {
        analytics.webXR.setFirstTranslation();
        setActionAlreadySeen('translate');
    }, { once: true });
    document.addEventListener(Events.r2uWebxrRotating, () => {
        analytics.webXR.setFirstRotation();
        setActionAlreadySeen('rotate');
    }, { once: true });
    document.addEventListener(Events.r2uWebxrReset, analytics.webXR.setReset, {
        once: true,
    });
    // Fallback
    document.addEventListener(Events.r2uWebxrFallbackToSceneviewer, analytics.webXR.onSceneViewerFallback, { once: true });
    window.addEventListener('hashchange', () => {
        if (window.location.hash === HASH_FALLBACK)
            analytics.webXR.onFallback();
    }, {
        once: true,
    });
    // Stopper events
    document.addEventListener(Events.r2uWebxrShare, analytics.webXR.onShare);
    document.addEventListener(Events.r2uWebxrExit, analytics.webXR.onExit);
    document.addEventListener(Events.r2uWebxrCallToAction, analytics.webXR.onCallToAction);
    // onLike | onDislike added to modal buttons
    // Count occurrences events
    document.addEventListener(Events.r2uWebxrTranslating, analytics.webXR.onTranslation);
    document.addEventListener(Events.r2uWebxrRotating, analytics.webXR.onRotation);
};
function attach({ sku, price, element, callToAction, event = 'click', showInstructions = 'once', showFeedback = true, fallbackOptions = { alertMessage }, }) {
    return __awaiter(this, void 0, void 0, function* () {
        if (!state.init)
            return Promise.reject(new Error('R2U - Not initialized'));
        if (!sku)
            return Promise.reject(new Error('R2U - Missing SKU'));
        const { activateWebXR, activateAR, WebXREvents } = yield arComponents;
        const shouldShowWebXR = () => __awaiter(this, void 0, void 0, function* () {
            const params = new URLSearchParams(window.location.search);
            if (params.has('r2u_ar_mode')) {
                return params.get('r2u_ar_mode') === 'webxr';
            }
            const userFingerprint = yield analytics.getFingerprint();
            state.growthbook = new GrowthBook({
                user: {
                    id: userFingerprint,
                },
                overrides: state.customer.experiments.overrides,
            });
            const experimentId = 'webxr-vs-sceneviewer-v3';
            const { value: variationId } = state.growthbook.run({
                key: experimentId,
                variations: ['sceneviewer-v3', 'webxr-v3'],
            });
            analytics.setExperimentId(experimentId);
            analytics.setVariationId(variationId);
            return variationId === 'webxr-v3';
        });
        const { glb, usdz, name, placement, sound, resize, pdpUrl } = yield product(sku);
        const scale = resize ? 'resizable' : 'fixed';
        const [currencyLocale, currencyFormat] = state.customer.language === 'pt' ? ['pt-BR', 'BRL'] : ['en-US', 'USD'];
        const cta = callToAction
            ? Object.assign(Object.assign({}, callToAction), { onClick: () => {
                    callToAction.onClick();
                    document.dispatchEvent(new Event('r2u-webxr-close'));
                    analytics.cta.onClick();
                } }) : undefined;
        const arProps = {
            glb,
            usdz,
            price,
            placement,
            scale,
            sound,
            callToAction: cta,
            pdpUrl,
            title: name,
            mode: 'ar_preferred',
        };
        const hasWaterMark = Boolean(state.customer.waterMarkPosition);
        const shouldShowFeedback = () => {
            const hasOpenedFeedback = getScreenAlreadyOpened('feedback');
            const customerShowFeedback = showFeedback && !hasOpenedFeedback;
            return customerShowFeedback;
        };
        const beforeClose = (container) => {
            const { open: openFeedback } = createFeedbackScreen({
                container,
                onLike: () => {
                    analytics.arLink.onLike();
                    analytics.webXR.onLike();
                },
                onDislike: () => {
                    analytics.arLink.onDislike();
                    analytics.webXR.onDislike();
                },
                onClose: () => document.dispatchEvent(new Event('r2u-webxr-close')),
                onOpen: () => setScreenAlreadyOpened('feedback'),
            });
            shouldShowFeedback()
                ? openFeedback()
                : document.dispatchEvent(new Event('r2u-webxr-close'));
        };
        const shouldShowInstructions = () => {
            switch (showInstructions) {
                case 'always':
                    return true;
                case 'never':
                    return false;
                default:
                case 'once':
                    const hasOpenedInstructions = getScreenAlreadyOpened('instructions');
                    return !hasOpenedInstructions;
            }
        };
        const showWebXRInstructions = () => {
            switch (showInstructions) {
                case 'always':
                    return { translate: true, rotate: true };
                case 'never':
                    return { translate: false, rotate: false };
                default:
                case 'once':
                    const hasSeenTranslate = getActionAlreadySeen('translate');
                    const hasSeenRotate = getActionAlreadySeen('rotate');
                    return { translate: !hasSeenTranslate, rotate: !hasSeenRotate };
            }
        };
        const webXRProps = {
            model: {
                name,
                description: price
                    ? new Intl.NumberFormat(currencyLocale, {
                        style: 'currency',
                        currency: currencyFormat,
                    }).format(Number(price))
                    : '',
                glb,
                placement,
                resizable: resize,
                url: pdpUrl,
                showInstructions: showWebXRInstructions(),
            },
            beforeClose,
            callToAction: cta,
            language: state.customer.language,
        };
        analytics.arLink.componentDidMount();
        const { open: openFallback, render: renderFallback } = createFallbackScreen({
            fallbackOptions,
            glb: arProps.glb,
        });
        const { open: openInstructions, render: renderInstructions } = createInstructionsScreen(Object.assign({ hasWaterMark,
            sku,
            activateAR, onOpen: () => setScreenAlreadyOpened('instructions') }, arProps));
        const { open: openFeedback } = createFeedbackScreen({
            container: document.body.appendChild(document.createElement('div')),
            onLike: () => analytics.arLink.onLike(),
            onDislike: () => analytics.arLink.onDislike(),
            onClose: () => undefined,
            onOpen: () => setScreenAlreadyOpened('feedback'),
        });
        const { open: openSocialFallback } = createSocialFallbackScreen();
        const setSku = (sku) => __awaiter(this, void 0, void 0, function* () {
            const newProduct = yield product(sku);
            arProps.glb = newProduct.glb;
            arProps.usdz = newProduct.usdz;
            arProps.placement = newProduct.placement;
            arProps.sound = newProduct.sound;
            arProps.scale = newProduct.resize ? 'resizable' : 'fixed';
            arProps.title = newProduct.name;
            webXRProps.model.glb = newProduct.glb;
            webXRProps.model.name = newProduct.name;
            webXRProps.model.placement = newProduct.placement;
            webXRProps.model.url = newProduct.pdpUrl;
            webXRProps.model.resizable = newProduct.resize;
            renderInstructions(arProps);
            renderFallback(arProps);
        });
        const arSessionListener = () => __awaiter(this, void 0, void 0, function* () {
            if (isIOSInAppBrowser()) {
                openSocialFallback();
                return;
            }
            // If on android, get A/B test data to show webXR or scene-viewer
            // If product placement equals to wall, show AR in scene-viewer
            // Do not await webXR to compute analytics click event
            if (IS_ANDROID && placement !== 'wall' && (yield shouldShowWebXR())) {
                attachWebXREventListeners(WebXREvents);
                activateWebXR(webXRProps);
            }
            // If it falls to scene-viewer, check if should show instructions screen
            else if (shouldShowInstructions())
                openInstructions();
            // If it does not show instructions, open scene-viewer AR experience
            else
                activateAR(arProps);
            yield analytics.arLink.onClick();
            const timeOnEvent = new Date().getTime();
            const sceneViewerEndHandler = () => {
                if (document.hidden)
                    return;
                const timeOnClose = new Date().getTime();
                analytics.arLink.onSessionTimeCollect(timeOnClose - timeOnEvent);
                shouldShowFeedback() && openFeedback();
                document.removeEventListener('visibilitychange', sceneViewerEndHandler);
            };
            const webxrEndHandler = () => {
                const timeOnClose = new Date().getTime();
                analytics.arLink.onSessionTimeCollect(timeOnClose - timeOnEvent);
                document.removeEventListener('r2u-webxr-close', webxrEndHandler);
                document.removeEventListener('visibilitychange', sceneViewerEndHandler);
            };
            document.addEventListener('r2u-webxr-close', webxrEndHandler);
            document.addEventListener('visibilitychange', sceneViewerEndHandler);
        });
        element.addEventListener(event, arSessionListener);
        const locationUrl = new URL(window.location.href);
        const autoOpenAR = locationUrl.searchParams.get('r2u_redirect') === 'true';
        const autoOpenARSku = locationUrl.searchParams.get('r2u_sku');
        if (autoOpenAR && !state.hasAutoOpenedAR) {
            state.hasAutoOpenedAR = true;
            if (autoOpenARSku) {
                yield setSku(autoOpenARSku);
            }
            open({ element, event });
        }
        window.addEventListener('hashchange', () => {
            if (window.location.hash === HASH_FALLBACK) {
                analytics.arLink.onFallback();
                element.removeEventListener(event, arSessionListener);
                element.addEventListener(event, openFallback);
                open({ element, event });
            }
        }, { once: true });
        return { setSku };
    });
}
function getLink(sku) {
    return __awaiter(this, void 0, void 0, function* () {
        if (!state.init)
            return Promise.reject(new Error('R2U - Not initialized'));
        if (!sku)
            return Promise.reject(new Error('R2U - Missing SKU'));
        const customerId = state.customer._id;
        const link = (yield get(`/sdk-ar/openar-link?customerId=${customerId}&productSku=${sku}`));
        return Promise.resolve(link);
    });
}
export default {
    attach,
    open,
    getLink,
};
//# sourceMappingURL=ar.js.map