"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LoadChannelModelUC = exports.SCENE_MODEL_DATA_ASSET_LINK_TYPE = void 0;
exports.makeLoadChannelModelUC = makeLoadChannelModelUC;
const core_1 = require("@vived/core");
const Dispatcher_1 = require("../../Dispatcher");
const GLBModel_1 = require("../../GLBModel");
const Entities_1 = require("../Entities");
const ChannelModelViewFactory_1 = require("./ChannelModelViewFactory");
exports.SCENE_MODEL_DATA_ASSET_LINK_TYPE = "default_model_data";
class LoadChannelModelUC extends core_1.AppObjectUC {
    static get(appObjects) {
        return (0, core_1.getSingletonComponent)(LoadChannelModelUC.type, appObjects);
    }
}
exports.LoadChannelModelUC = LoadChannelModelUC;
LoadChannelModelUC.type = "LoadChannelModelUC";
function makeLoadChannelModelUC(appObject) {
    return new LoadChannelModelUCImp(appObject);
}
class LoadChannelModelUCImp extends LoadChannelModelUC {
    get channelModelRepo() {
        return this.getCachedSingleton(Entities_1.ChannelModelRepo.type);
    }
    get loadGlbFile() {
        return this.getCachedSingleton(GLBModel_1.LoadGlbFileUC.type);
    }
    get glbRepo() {
        return this.getCachedSingleton(GLBModel_1.GlbModelRepo.type);
    }
    get channelModelViewFactory() {
        return this.getCachedSingleton(ChannelModelViewFactory_1.ChannelModelViewFactory.type);
    }
    get getAssetBlob() {
        return this.getCachedSingleton(Dispatcher_1.GetAssetBlobURLUC.type)
            ?.doDispatch;
    }
    get getLinkedAsset() {
        return this.getCachedSingleton(Dispatcher_1.GetLinkedAssetsUC.type)
            ?.doDispatch;
    }
    get showSpinner() {
        return this.getCachedSingleton(Dispatcher_1.ShowSpinnerUC.type)
            ?.showSpinner;
    }
    waitForExistingToLoad(existing) {
        return new Promise((resolve, reject) => {
            const onExistingModelChange = () => {
                if (existing.state === Entities_1.ChannelModelState.READY) {
                    existing.removeChangeObserver(onExistingModelChange);
                    resolve(existing);
                }
                else if (existing.state === Entities_1.ChannelModelState.ERROR) {
                    existing.removeChangeObserver(onExistingModelChange);
                    reject(existing.modelError);
                }
            };
            existing.addChangeObserver(onExistingModelChange);
        });
    }
    constructor(appObject) {
        super(appObject, LoadChannelModelUC.type);
        this.loadChannelModel = (modelID) => {
            if (!this.channelModelRepo ||
                !this.glbRepo ||
                !this.loadGlbFile ||
                !this.getAssetBlob ||
                !this.getLinkedAsset ||
                !this.channelModelViewFactory ||
                !this.showSpinner) {
                this.error("Missing Component(s)");
                return Promise.reject(new Error("Missing Component(s)"));
            }
            const existingChannelModel = this.channelModelRepo.getForAppObject(modelID);
            if (existingChannelModel) {
                if (existingChannelModel.state === Entities_1.ChannelModelState.READY) {
                    return Promise.resolve(existingChannelModel);
                }
                else if (existingChannelModel.state === Entities_1.ChannelModelState.LOADING) {
                    return this.waitForExistingToLoad(existingChannelModel);
                }
                else if (existingChannelModel.state === Entities_1.ChannelModelState.ERROR) {
                    return Promise.reject(existingChannelModel.modelError);
                }
            }
            const channelModel = this.channelModelRepo.createChannelModel(modelID);
            channelModel.state = Entities_1.ChannelModelState.LOADING;
            const getLinkedAsset = this.getLinkedAsset;
            const getAssetBlob = this.getAssetBlob;
            const channelModelViewFactory = this.channelModelViewFactory;
            let closeSpinner = () => { };
            return this.showSpinner("Loading Model", "Loading channel model...")
                .then((closeCB) => {
                closeSpinner = closeCB;
                return getAssetBlob(modelID);
            })
                .then((blobURL) => {
                const glbModel = this.glbRepo.createGlbModel(modelID);
                return this.loadGlbFile.loadBlobURL(blobURL, glbModel);
            })
                .then(() => {
                return getLinkedAsset(modelID, exports.SCENE_MODEL_DATA_ASSET_LINK_TYPE);
            })
                .then((dataAssets) => {
                if (dataAssets.length === 0) {
                    return Promise.reject(new Error("Model asset does not have data"));
                }
                return getAssetBlob(dataAssets[0].id);
            })
                .then((blobURL) => {
                return this.blobToJSON(blobURL);
            })
                .then((dto) => {
                channelModel.setupFromData(dto);
                channelModelViewFactory.initializeView(channelModel);
                channelModel.state = Entities_1.ChannelModelState.READY;
                closeSpinner();
                return channelModel;
            })
                .catch((e) => {
                closeSpinner();
                return Promise.reject(e);
            });
        };
        this.blobToJSON = (url) => {
            return fetch(url).then((resp) => {
                return resp.json();
            });
        };
        this.appObjects.registerSingleton(this);
    }
}
//# sourceMappingURL=LoadChannelModelUC.js.map