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());
    });
};
import React, { createRef } from 'react';
import ReactDOM from 'react-dom';
import QRCode from 'qrcode.react';
import state from '../state';
import R2UModelViewer from '../components/R2UModelViewer';
import Viewer from '@r2u/viewer';
import product from '../services/product';
import * as analytics from '../services/analytics';
import { getCustomizedModel, requestConversion, retryCheckConversion, uploadCustomization, } from '../services/customization';
import { activateAR } from '@r2u/react-ar-components';
import sortCustomization from 'src/utils/sortCustomization';
import { ViewerError } from 'src/error/ViewerError';
const create = ({ element, sku, name, popup = true, progressBarPosition = 'top', progressBarColor, poster, autoRotate = true, viewerProps, }) => __awaiter(void 0, void 0, void 0, function* () {
    return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
        if (!state.init)
            return reject(new Error('R2U - Not initialized'));
        if (!sku)
            return reject(new Error('R2U - Missing SKU'));
        const { glb, name: productName, viewerOptions: productViewerOptions, } = yield product(sku);
        let glbSrc = glb;
        const waterMarkPosition = state.customer.waterMarkPosition;
        const viewerOptions = productViewerOptions || state.customer.viewerOptions || undefined;
        const refViewer = createRef();
        const refViewerPopup = createRef();
        const refViewerFunctions = createRef();
        const refR2UModelViewer = createRef();
        const setSku = (sku) => __awaiter(void 0, void 0, void 0, function* () {
            return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
                var _a, _b;
                try {
                    const { glb } = yield product(sku);
                    glbSrc = glb;
                    yield ((_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.updateGlb(glb));
                    (_b = refR2UModelViewer.current) === null || _b === void 0 ? void 0 : _b.updateGlb(glb);
                    resolve();
                }
                catch (e) {
                    reject(e);
                }
            }));
        });
        const insertModelNode = (...args) => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.insertModelNode(...args);
        };
        const insertSlotModelNode = (...args) => __awaiter(void 0, void 0, void 0, function* () {
            var _c;
            yield ((_c = refViewerFunctions.current) === null || _c === void 0 ? void 0 : _c.insertSlotModelNode(...args));
        });
        const deleteModelNode = (...args) => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.deleteModelNode(...args);
        };
        const updateBloom = (...args) => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.updateBloom(...args);
        };
        const loadMaterials = ({ sku, glb, }) => __awaiter(void 0, void 0, void 0, function* () {
            var _d, _e;
            if (glb)
                return ((_d = refViewerFunctions.current) === null || _d === void 0 ? void 0 : _d.loadMaterials(glb)) || false;
            if (sku) {
                const { glb: glbUrl } = yield product(sku);
                return ((_e = refViewerFunctions.current) === null || _e === void 0 ? void 0 : _e.loadMaterials(glbUrl)) || false;
            }
            return false;
        });
        const setMaterial = (...args) => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.setMaterial(...args);
        };
        const setCustomMaterial = (...args) => {
            var _a;
            return (((_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.setCustomMaterial(...args)) ||
                Promise.resolve(false));
        };
        const getAllSlotsMaterials = () => { var _a; return ((_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.getAllSlotsMaterials()) || null; };
        const getAllSlotsModels = () => { var _a; return ((_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.getAllSlotsModels()) || null; };
        const setModel = (...args) => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.setModel(...args);
        };
        const setCamera = (...args) => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.setCamera(...args);
        };
        const updateShadow = (...args) => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.updateShadow(...args);
        };
        const updateFog = (...args) => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.updateFog(...args);
        };
        const updateBloomProps = (...args) => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.updateBloomProps(...args);
        };
        const updateEnvironment = (...args) => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.updateEnvironment(...args);
        };
        const getCamera = () => { var _a; return ((_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.getCamera()) || null; };
        const getCustomizationAR = (customMaterial, draco = true) => __awaiter(void 0, void 0, void 0, function* () {
            try {
                if (!refViewerFunctions.current)
                    throw new ViewerError('Viewer not completely loaded!');
                let customization = null;
                try {
                    customization =
                        refViewerFunctions.current.getCurrentCustomization(customMaterial);
                }
                catch (e) {
                    console.error(`Error on get current customization: ${e.message}`);
                }
                if (!customization)
                    throw new ViewerError('No customization returned!');
                sortCustomization(customization);
                const customizationAR = yield getCustomizedModel(sku, customization);
                if (!customizationAR.glb) {
                    let customizationBlob = null;
                    try {
                        customizationBlob =
                            yield refViewerFunctions.current.getCustomizedModel(draco);
                    }
                    catch (e) {
                        console.error(`Error on export the customization glb: ${e.message}`);
                    }
                    if (!customizationBlob)
                        throw new ViewerError('Could not export the customization glb!');
                    customizationAR.glb = yield uploadCustomization(sku, customization, customizationBlob);
                }
                if (!customizationAR.usdz) {
                    const conversion = yield requestConversion(sku, 
                    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                    customizationAR.glb.split('/').pop());
                    if ((yield retryCheckConversion(conversion.jobId)) === 'success')
                        customizationAR.usdz = conversion.usdz;
                    else
                        throw new ViewerError('Error while converting to usdz!');
                }
                getCustomizedModel(sku, customization);
                return customizationAR;
            }
            catch (e) {
                console.error(`Error getting customization AR: ${e.message}`);
                return Promise.reject(e);
            }
        });
        // viewerFuctions.customization.openAR
        const openAR = (customMaterial = false, draco = true) => __awaiter(void 0, void 0, void 0, function* () {
            try {
                const customizationAR = yield getCustomizationAR(customMaterial, draco);
                activateAR({
                    glb: customizationAR.glb,
                    usdz: customizationAR.usdz,
                    mode: 'ar_preferred',
                });
                return true;
            }
            catch (error) {
                console.error(`Error opening AR: ${error.message}`);
                return false;
            }
        });
        // viewerFuctions.customization.renderQRCode
        const renderQRCode = (element, customMaterial = false, draco = true) => __awaiter(void 0, void 0, void 0, function* () {
            try {
                const customizationAR = yield getCustomizationAR(customMaterial, draco);
                const qrCodeUrl = `https://viewer.r2u.io/?customizationUri=${encodeURIComponent(customizationAR.glb
                    .replace('https://storage.googleapis.com/', '')
                    .replace(/\.glb$/, ''))}&autoOpen=1`;
                ReactDOM.render(React.createElement(QRCode, Object.assign({}, { 'data-url': qrCodeUrl }, { value: qrCodeUrl, style: { width: '100%', height: '100%' }, renderAs: "svg" })), element);
                return true;
            }
            catch (error) {
                console.error(`Error generating QR Code: ${error.message}`);
                return false;
            }
        });
        // viewerFuctions.customization.getViewerURL
        const getViewerURL = (customMaterial = false, draco = true) => __awaiter(void 0, void 0, void 0, function* () {
            try {
                const customizationAR = yield getCustomizationAR(customMaterial, draco);
                const viewerUrl = `https://viewer.r2u.io/?customizationUri=${encodeURIComponent(customizationAR.glb
                    .replace('https://storage.googleapis.com/', '')
                    .replace(/\.glb$/, ''))}&autoOpen=1`;
                return viewerUrl;
            }
            catch (error) {
                console.error(`Error generating viewer URL: ${error.message}`);
                return null;
            }
        });
        const downloadGlb = (...args) => {
            if (!refViewerFunctions.current)
                return;
            refViewerFunctions.current.downloadGlb(...args);
        };
        const waitForFunctions = (callback) => __awaiter(void 0, void 0, void 0, function* () {
            const interval = setInterval(() => {
                if (refViewerFunctions.current) {
                    clearInterval(interval);
                    callback();
                }
            }, 200);
            setTimeout(() => {
                if (!refViewerFunctions.current) {
                    clearInterval(interval);
                    throw new Error('Internal error: Unable to load viewerRefFunctions.');
                }
            }, 10000);
        });
        const insertHotspot = (...args) => __awaiter(void 0, void 0, void 0, function* () {
            yield waitForFunctions(() => { var _a; return (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.insertHotspot(...args); });
        });
        const updateHotspot = (...args) => __awaiter(void 0, void 0, void 0, function* () {
            yield waitForFunctions(() => { var _a; return (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.updateHotspot(...args); });
        });
        const deleteHotspot = (...args) => __awaiter(void 0, void 0, void 0, function* () {
            yield waitForFunctions(() => { var _a; return (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.deleteHotspot(...args); });
        });
        const showHotspot = (...args) => __awaiter(void 0, void 0, void 0, function* () {
            yield waitForFunctions(() => { var _a; return (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.showHotspot(...args); });
        });
        const hideHotspot = (...args) => __awaiter(void 0, void 0, void 0, function* () {
            yield waitForFunctions(() => { var _a; return (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.hideHotspot(...args); });
        });
        const focusHotspot = (...args) => __awaiter(void 0, void 0, void 0, function* () {
            yield waitForFunctions(() => { var _a; return (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.focusHotspot(...args); });
        });
        const getActiveHotspotId = () => { var _a; return ((_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.getActiveHotspotId()) || null; };
        const lookToHotspot = (...args) => __awaiter(void 0, void 0, void 0, function* () {
            yield waitForFunctions(() => { var _a; return (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.lookToHotspot(...args); });
        });
        const getSceneTree = () => { var _a; return ((_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.getSceneTree()) || null; };
        const playAnimation = (...args) => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.playAnimation(...args);
        };
        const pauseAnimation = () => {
            var _a;
            (_a = refViewerFunctions.current) === null || _a === void 0 ? void 0 : _a.pauseAnimation();
        };
        const stopAnimation = (...args) => __awaiter(void 0, void 0, void 0, function* () {
            var _f;
            (_f = refViewerFunctions.current) === null || _f === void 0 ? void 0 : _f.stopAnimation(...args);
        });
        const takeSnapshot = (...args) => __awaiter(void 0, void 0, void 0, function* () { var _g; return ((_g = refViewerFunctions.current) === null || _g === void 0 ? void 0 : _g.takeSnapshot(...args)) || null; });
        const updateBackground = (...args) => __awaiter(void 0, void 0, void 0, function* () {
            var _h;
            (_h = refViewerFunctions.current) === null || _h === void 0 ? void 0 : _h.updateBackground(...args);
        });
        const resolvePromise = () => {
            resolve({
                setSku,
                insertModelNode,
                insertSlotModelNode,
                deleteModelNode,
                loadMaterials,
                setMaterial,
                setCustomMaterial,
                getAllSlotsMaterials,
                updateBloom,
                getAllSlotsModels,
                setModel,
                setCamera,
                updateShadow,
                updateFog,
                updateBloomProps,
                updateEnvironment,
                getCamera,
                insertHotspot,
                updateHotspot,
                deleteHotspot,
                showHotspot,
                hideHotspot,
                focusHotspot,
                getActiveHotspotId,
                lookToHotspot,
                customization: { openAR, renderQRCode, getViewerURL },
                getSceneTree,
                playAnimation,
                pauseAnimation,
                stopAnimation,
                downloadGlb,
                takeSnapshot,
                updateBackground,
            });
        };
        ReactDOM.render(React.createElement(R2UModelViewer, Object.assign({ ref: refR2UModelViewer, alt: name || productName, autoRotate: autoRotate, poster: poster, refViewer: refViewer, refViewerPopup: refViewerPopup, refViewerFunctions: refViewerFunctions, waterMarkPosition: waterMarkPosition, progressBarPosition: progressBarPosition, progressBarColor: progressBarColor, popup: popup }, viewerOptions, viewerProps, { componentDidMount: analytics.arModelViewer.componentDidMount, onClick: (e) => {
                analytics.arModelViewer.onClick();
                if (viewerProps === null || viewerProps === void 0 ? void 0 : viewerProps.onClick)
                    viewerProps === null || viewerProps === void 0 ? void 0 : viewerProps.onClick(e);
            }, onSessionTimeCollect: analytics.arModelViewer.onSessionTimeCollect, ModelViewerElement: Viewer, onLoad: resolvePromise, glbSrc: glbSrc })), element);
    }));
});
export default {
    create,
};
//# sourceMappingURL=viewer.js.map