import {http2} from "./Http2.js"
import XSubSequence from "./XSubSequence.js"

const DefaultUrlTransformer = async i=>typeof i != "string" ? (console.warn("url transformer error", i),
i) : i.startsWith("blob:") ? i : http2.get({
    url: i,
    useIndexedDb: !0,
    key: "url"
});

export default class XSequence {
    constructor(e, t, r="test", n=DefaultUrlTransformer) {
        E(this, "_scene");
        E(this, "_name");
        E(this, "_subSeqs");
        E(this, "_animGroup");
        E(this, "_targetSubSeqs");
        E(this, "_abosoluteUrl");
        E(this, "_rootDir");
        E(this, "urlTransformer");
        E(this, "init", async()=>new Promise(e=>{
            this.urlTransformer(this._abosoluteUrl).then(t=>{
                const r = new XMLHttpRequest;
                r.open("get", t),
                r.send(null),
                r.onload = ()=>{
                    if (r.status == 200) {
                        const n = JSON.parse(r.responseText);
                        this.load(n).then(()=>{
                            e()
                        }
                        )
                    }
                }
            }
            )
        }
        ));
        E(this, "getRootOfSubSeqs", ()=>{
            const e = new Array;
            return this._subSeqs.forEach(t=>{
                e.push(t.root)
            }
            ),
            e
        }
        );
        E(this, "play", async(e=!0)=>new Promise(t=>{
            this._animGroup.play(e),
            e ? this._animGroup.onAnimationGroupLoopObservable.addOnce(()=>{
                t()
            }
            ) : this._animGroup.onAnimationGroupEndObservable.addOnce(()=>{
                t()
            }
            )
        }
        ));
        E(this, "goToFrame", e=>{
            this._animGroup.goToFrame(e)
        }
        );
        E(this, "hide", ()=>{
            this._subSeqs.forEach(e=>{
                e.hide()
            }
            )
        }
        );
        E(this, "show", ()=>{
            this._subSeqs.forEach(e=>{
                e.show()
            }
            )
        }
        );
        E(this, "pause", ()=>{
            this._animGroup.pause()
        }
        );
        E(this, "reset", ()=>{
            this._animGroup.reset()
        }
        );
        this._scene = e,
        this._abosoluteUrl = t,
        this._rootDir = t.split("/").slice(0, -1).join("/") + "/",
        this._name = r,
        this._subSeqs = new Map,
        this._animGroup = new BABYLON.AnimationGroup("Seq_" + r,e),
        this._targetSubSeqs = new Map,
        this._animGroup.onAnimationGroupPlayObservable.add(()=>{
            this._subSeqs.forEach(o=>{
                o.show()
            }
            )
        }
        ),
        this._animGroup.onAnimationGroupEndObservable.add(()=>{
            this._subSeqs.forEach(o=>{
                o.hide()
            }
            )
        }
        ),
        this.urlTransformer = n
    }
    get animGroup() {
        return this._animGroup
    }
    serialize() {
        const e = {};
        return e.SubSequence = new Array,
        e.TimeLine = new Array,
        this._subSeqs.forEach(t=>{
            const r = {
                name: t.name,
                uri: t.path
            };
            e.SubSequence.push(r);
            const n = this._targetSubSeqs.get(t);
            n && e.TimeLine.push({
                frame: n == null ? void 0 : n.frame,
                position: n.position,
                rotation: n.rotation,
                scaling: n.scaling,
                name: t.name
            })
        }
        ),
        e
    }
    get isPlaying() {
        return this._animGroup.isPlaying
    }
    get isStarted() {
        return this._animGroup.isStarted
    }
    get loaded() {
        let e = !0;
        return this._subSeqs.forEach(t=>{
            e = e && t.loaded
        }
        ),
        e
    }
    dispose() {
        this._subSeqs.forEach(e=>{
            e.dispose()
        }
        ),
        this.animGroup.dispose()
    }
    setFrame(e, t) {
        const r = this._subSeqs.get(e);
        if (r) {
            const n = this._targetSubSeqs.get(r);
            n && (n.frame = t),
            n && this.update(r, n)
        }
    }
    get name() {
        return this._name
    }
    update(e, t) {
        if (t) {
            const r = {
                frame: t.frame,
                scaling: new BABYLON.Vector3(t.scaling[0],t.scaling[1],t.scaling[2]),
                position: new BABYLON.Vector3(t.position[0],t.position[1],t.position[2]),
                rotation: new BABYLON.Vector3(t.rotation[0] / 180 * Math.PI,t.rotation[1] / 180 * Math.PI,t.rotation[2] / 180 * Math.PI),
                name: t.name
            }
              , n = this._subSeqs.get(r.name);
            n && (n.setPositionVector(r.position),
            n.setRotationVector(r.rotation),
            n.setScalingVector(r.scaling),
            n.setStartFrame(r.frame),
            this._targetSubSeqs.set(n, t),
            n.onSubSequenceTransformationChangeObservable.add(()=>{
                const o = this._targetSubSeqs.get(n);
                o && (o.position = [n.pos.x, n.pos.y, n.pos.z]),
                o && (o.rotation = [n.rot.x, n.rot.y, n.rot.z]),
                o && (o.scaling = [n.scal.x, n.scal.y, n.scal.z])
            }
            ))
        }
    }
    load(e) {
        return new Promise((t,r)=>{
            const n = new Array
              , o = e.SubSequence
              , a = e.TimeLine;
            for (const s of o) {
                s.uri.indexOf("./") == 0 && (s.uri = s.uri.slice(2));
                const l = new XSubSequence(this._scene,this._rootDir + s.uri,this.urlTransformer);
                this._subSeqs.set(s.name, l),
                n.push(l.init())
            }
            Promise.all(n).then(()=>{
                a.forEach(s=>{
                    const l = this._subSeqs.get(s.name);
                    l && this.update(l, s)
                }
                ),
                this._subSeqs.forEach(s=>{
                    s.animGroup.targetedAnimations.forEach(l=>{
                        this._animGroup.addTargetedAnimation(l.animation, l.target)
                    }
                    )
                }
                ),
                t()
            }
            , ()=>{
                r()
            }
            )
        }
        )
    }
}