export default class XAvatarLoader {
    constructor() {
        E(this, "containers", new Map);
        E(this, "meshes", new Map);
        E(this, "animations", new Map);
        E(this, "aniPath", new Map);
        E(this, "binPath", new Map);
        E(this, "texPath", new Map);
        E(this, "matPath", new Map);
        E(this, "mshPath", new Map);
        E(this, "rootPath", new Map);
        E(this, "meshTexList", new Map);
        E(this, "_enableIdb", !0);
        E(this, "_mappings", new Map);
        E(this, "_sharedTex", new Map);
        E(this, "avaliableAnimation", new Map);
        E(this, "enableShareTexture", !0);
        E(this, "enableShareAnimation", !0);
        E(this, "fillEmptyLod", !0);
        const e = new BABYLON.GLTFFileLoader;
        BABYLON.SceneLoader.RegisterPlugin(e),
        e.preprocessUrlAsync = function(t) {
            const r = avatarLoader._mappings.get(t);
            return r ? Promise.resolve(r) : Promise.resolve(t)
        }
    }
    getParsedUrl(e, t, r, n="") {
        return new Promise((o,a)=>{
            if (!r || r.indexOf(".zip") === -1)
                return o(r);
            const s = this.rootPath.get(r);
            if (s)
                return o(s);
            {
                const l = ".zip"
                  , u = r.replace(l, "") + COMPONENT_LIST_PREFIX;
                e.urlTransformer(u, !0).then(c=>{
                    if (!c)
                        return a("Loading Failed");
                    new Response(c).json().then(h=>{
                        var _, g, m, v, y, b, T;
                        const f = r.replace(l, "")
                          , d = f + ((_ = h == null ? void 0 : h.components) == null ? void 0 : _.url.replace("./", ""));
                        if (this.rootPath.set(r, d),
                        h.components ? (h.components.url && this.mshPath.set(t, f + "/" + ((g = h == null ? void 0 : h.components) == null ? void 0 : g.url.replace("./", ""))),
                        h.components.url_lod2 && this.mshPath.set(t + "_" + avatarSetting.lod[1].level, f + "/" + ((m = h == null ? void 0 : h.components) == null ? void 0 : m.url_lod2.replace("./", ""))),
                        h.components.url_lod4 && this.mshPath.set(t + "_" + avatarSetting.lod[2].level, f + "/" + ((v = h == null ? void 0 : h.components) == null ? void 0 : v.url_lod4.replace("./", "")))) : (h.meshes.url && this.mshPath.set(t, f + "/" + ((y = h == null ? void 0 : h.meshes) == null ? void 0 : y.url.replace("./", ""))),
                        h.meshes.url_lod2 && this.mshPath.set(t + "_" + avatarSetting.lod[1].level, f + "/" + ((b = h == null ? void 0 : h.meshes) == null ? void 0 : b.url_lod2.replace("./", ""))),
                        h.meshes.url_lod4 && this.mshPath.set(t + "_" + avatarSetting.lod[2].level, f + "/" + ((T = h == null ? void 0 : h.meshes) == null ? void 0 : T.url_lod4.replace("./", "")))),
                        h.materials && h.materials.forEach(C=>{
                            const A = f + "/" + C.url;
                            this.matPath.set(C.name, A)
                        }
                        ),
                        h.bin) {
                            const C = f + "/" + h.bin.url;
                            this.binPath.set(t, C);
                            const A = f + "/" + h.bin.url_lod2;
                            this.binPath.set(t + "_" + avatarSetting.lod[1].level, A);
                            const S = f + "/" + h.bin.url_lod4;
                            this.binPath.set(t + "_" + avatarSetting.lod[2].level, S)
                        }
                        return h.textures && h.textures.forEach(C=>{
                            const A = f + "/" + C.url;
                            this.texPath.set(C.url, A);
                            const S = this.meshTexList.get(h.components.url);
                            C.type === "png" && (S ? S.find(P=>P === C.name) || S.push(C.url) : this.meshTexList.set(t, [C.name]))
                        }
                        ),
                        o(d)
                    }
                    ).catch(h=>{
                        logger.error(`[Engine] parse json file error,${h}`)
                    }
                    )
                }
                ).catch(c=>{
                    logger.error(`[Engine] ulrtransform error, cannot find resource in db,${c}`)
                }
                )
            }
        }
        )
    }
    async parse(e, t) {
        const r = [];
        t.forEach(n=>{
            this._setAnimationList(n.id, n.animations),
            r.push(this.getParsedUrl(e, n.id, n.url)),
            n.components.forEach(o=>{
                o.units.forEach(a=>{
                    r.push(this.getParsedUrl(e, a.name, a.url))
                }
                )
            }
            )
        }
        ),
        await Promise.all(r)
    }
    _setAnimationList(e, t) {
        t ? t.forEach(r=>{
            this.aniPath.set(e + "_" + r.name, r.url)
        }
        ) : logger.error("[Engine] no animation list exist, please check config for details")
    }
    disposeContainer() {
        this.containers.forEach((e,t)=>{
            e.xReferenceCount < 1 && (this.enableShareTexture && e.textures.length > 0 && e.textures[0].xReferenceCount != null && (e.textures[0].xReferenceCount--,
            e.textures = []),
            e.dispose(),
            this.containers.delete(t))
        }
        ),
        this._sharedTex.forEach((e,t)=>{
            e.xReferenceCount == 0 && (e.dispose(),
            this._sharedTex.delete(t))
        }
        )
    }
    set enableIdb(e) {
        this._enableIdb = e
    }
    getGlbPath(e) {
        return this.aniPath.get(e + ".glb")
    }
    getGltfPath(e) {
        return this.mshPath.get(e + ".gltf")
    }
    getPngUrl(e) {
        return this.texPath.get(e + ".png")
    }
    getMeshUrl(e) {
        return this.mshPath.get(e)
    }
    _getSourceKey(e, t) {
        return t && avatarSetting.lod[t] ? e + avatarSetting.lod[t].fileName.split(".")[0] : e
    }
    _getAnimPath(e, t) {
        let r = this.aniPath.get(t + "_animations_" + t.split("_")[1]);
        return r || (r = this.aniPath.get(t + "_" + e)),
        r
    }
    load(e, t, r, n) {
        return new Promise((o,a)=>{
            this.loadGlb(e, t, r).then(s=>s ? o(s) : a("[Engine] container load failed")).catch(()=>a("[Engine] container load failed"))
        }
        )
    }
    _searchAnimation(e, t) {
        let r;
        return this.containers.forEach((n,o)=>{
            const a = t.split("_")[0];
            o.indexOf(a) != -1 && o.indexOf(e) != -1 && (r = n)
        }
        ),
        r
    }
    loadAnimRes(e, t, r) {
        return new Promise((n,o)=>{
            const a = this._getAnimPath(t, r)
              , s = getAnimationKey(t, r);
            if (a && this.containers.get(a))
                return n(this.containers.get(a));
            if (a)
                this._loadGlbFromBlob(e, s, a).then(l=>l.animationGroups.length == 0 ? (this.containers.delete(s),
                l.dispose(),
                Promise.reject("container does not contains animation data")) : n(l));
            else
                return o("no such url")
        }
        )
    }
    loadGlb(e, t, r) {
        let n = this.getMeshUrl(this._getSourceKey(t, r));
        return !n && this.fillEmptyLod && (r = 0,
        n = this.getMeshUrl(this._getSourceKey(t, r))),
        n && this.containers.get(n) ? Promise.resolve(this.containers.get(n)) : n ? this._enableIdb ? Promise.resolve(this._loadGlbFromBlob(e, this._getSourceKey(t, r), n)) : Promise.resolve(this._loadGlbFromUrl(e, this._getSourceKey(t, r), n)) : Promise.reject("no such url")
    }
    loadGltf(e, t, r, n) {
        const o = this._getSourceKey(t, r || 0);
        let a = this.getGltfPath(o);
        return !a && this.fillEmptyLod && (a = this.getGltfPath(t)),
        a && this.containers.get(a) ? Promise.resolve(this.containers.get(a)) : this._enableIdb ? this._loadGltfFromBlob(e, t, r, n) : a ? this._loadGltfFromUrl(e, t, a.replace(t + ".gltf", "")) : Promise.reject()
    }
    loadSubsequence() {}
    loadVAT() {}
    getResourceName(e) {
        return this.meshTexList.get(e)
    }
    _loadGltfFromUrl(e, t, r) {
        return BABYLON.SceneLoader.LoadAssetContainerAsync(r, t + ".gltf", e.Scene, null, ".gltf")
    }
    _loadGlbFromBlob(e, t, r) {
        return new Promise((n,o)=>{
            e.urlTransformer(r).then(a=>{
                BABYLON.SceneLoader.LoadAssetContainerAsync("", a, e.Scene, null, ".glb").then(s=>{
                    if (s) {
                        if (this.enableShareTexture && s.textures.length > 0) {
                            const l = t.indexOf("_lod") != -1 ? t.slice(0, -5) : t
                              , u = this._sharedTex.get(l);
                            u ? (s.meshes[1].material._albedoTexture = u,
                            s.textures.forEach(c=>{
                                c.dispose()
                            }
                            ),
                            s.textures = [u],
                            u.xReferenceCount++) : (this._sharedTex.set(l, s.textures[0]),
                            s.textures[0].xReferenceCount = 1)
                        }
                        return s.addAllToScene(),
                        s.xReferenceCount = 0,
                        s.meshes.forEach(l=>{
                            l.setEnabled(!1)
                        }
                        ),
                        this.containers.set(r, s),
                        n(s)
                    } else
                        o("glb file load failed")
                }
                )
            }
            )
        }
        )
    }
    _loadGlbFromUrl(e, t, r) {
        return new Promise((n,o)=>{
            BABYLON.SceneLoader.LoadAssetContainerAsync("", r, e.Scene, null, ".glb").then(a=>{
                if (a) {
                    if (a.addAllToScene(),
                    a.meshes.forEach(s=>{
                        s.setEnabled(!1)
                    }
                    ),
                    this.enableShareTexture && a.textures.length > 0) {
                        const s = t.indexOf("_lod") != -1 ? t.slice(0, -5) : t
                          , l = this._sharedTex.get(s);
                        l ? (a.meshes[1].material._albedoTexture = l,
                        a.textures.forEach(u=>{
                            u.dispose()
                        }
                        ),
                        a.textures = [l],
                        l.xReferenceCount++) : (this._sharedTex.set(s, a.textures[0]),
                        a.textures[0].xReferenceCount = 1)
                    }
                    return a.xReferenceCount = 0,
                    this.containers.set(r, a),
                    n(a)
                } else
                    o("glb file load failed")
            }
            )
        }
        )
    }
    _loadGltfFromBlob(e, t, r, n) {
        return new Promise((o,a)=>{
            const s = [];
            let l = this._getSourceKey(t, r)
              , u = this.getGltfPath(l);
            if (!u && this.fillEmptyLod && (r = 0,
            l = this._getSourceKey(t, r),
            u = this.getGltfPath(l)),
            !u)
                return a(`[Engine] gltf path incorrect ${l},cancel.`);
            const c = this.mshPath.get(l + ".gltf");
            if (!c)
                return a("cannot find asset mshPath");
            const h = this.binPath.get(l + ".bin");
            if (!h)
                return a("cannot find asset binPath");
            if (!n) {
                const _ = this.meshTexList.get(t);
                if (!_ || _.length == 0)
                    return a("cannot find texture");
                n = _[0]
            }
            const f = this.texPath.get(n + ".png");
            if (!f)
                return a();
            const d = this.texPath.get(n + "-astc.ktx");
            if (!d)
                return a();
            s.push(this._blobMapping(e, c)),
            s.push(this._blobMapping(e, h)),
            s.push(this._blobMapping(e, f)),
            s.push(this._blobMapping(e, d)),
            Promise.all(s).then(()=>{
                const _ = u.replace(l + ".gltf", "");
                BABYLON.SceneLoader.LoadAssetContainerAsync(_, l + ".gltf", e.Scene, null, ".gltf").then(g=>{
                    var v;
                    this.containers.set(u, g),
                    g.addAllToScene(),
                    g.meshes.forEach(y=>{
                        y.setEnabled(!1)
                    }
                    );
                    const m = this._sharedTex.get(t);
                    m ? ((v = g.meshes[1].material._albedoTexture) == null || v.dispose(),
                    g.meshes[1].material._albedoTexture = m) : this._sharedTex.set(t, g.meshes[1].material._albedoTexture),
                    o(g)
                }
                )
            }
            )
        }
        )
    }
    _blobMapping(e, t) {
        return new Promise((r,n)=>{
            e.urlTransformer(t).then(o=>o ? (this._mappings.set(t, o),
            r(t)) : n(`[Engine] url urlTransformer parse error ${t}`))
        }
        )
    }
}

const avatarLoader = new XAvatarLoader();
export { avatarLoader };