import Logger from "./Logger.js"

const logger = new Logger('XStateMachine')
export default class XStateMachine {
    constructor(e) {
        E(this, "state");
        E(this, "isMoving");
        E(this, "isRotating");
        E(this, "_observer");
        E(this, "_movingObserver");
        E(this, "_scene");
        this._scene = e
    }
    rotateTo(e, t, r, n) {
        return new Promise((o,a)=>{
            var h;
            const s = e.avatarManager.scene;
            if (r && e.setRotation(r),
            t == r)
                return o();
            e.priority === 0 && logger.info(`avatar ${e.id} starts to rotate from ${r} to ${t}`);
            let l = 0;
            const u = 1e3 / 25
              , c = calcDistance3DAngle(t, e.rotation) / u;
            this._movingObserver && s.onBeforeRenderObservable.remove(this._movingObserver),
            (h = e.controller) == null || h.playAnimation(n || "Walking", !0),
            this._movingObserver = s == null ? void 0 : s.onBeforeRenderObservable.add(()=>{
                var f;
                if (l < 1) {
                    if (!e.rootNode)
                        return e.setRotation(t),
                        o();
                    const d = BABYLON.Vector3.Lerp(e.rootNode.rotation, ue4Rotation2Xverse(t), l);
                    e.setRotation(xverseRotation2Ue4(d)),
                    l += u / (c * 1e3)
                } else
                    return s.onBeforeRenderObservable.remove(this._movingObserver),
                    (f = e.controller) == null || f.playAnimation("Idle", !0),
                    o()
            }
            )
        }
        )
    }
    _filterPathPoint(e) {
        let t = 0;
        const r = 1e-4;
        if (e.length <= 1)
            return [];
        for (; t < e.length - 1; )
            calcDistance3D(e[t], e[t + 1]) < r ? e.splice(t, 1) : t++;
        return e
    }
    moveTo(e, t, r, n, o, a) {
        return new Promise((s,l)=>{
            var m;
            const u = e.avatarManager.scene;
            e.priority === 0 && logger.info(`avatar ${e.id} starts to move from ${t} to ${r}`);
            let c = 0;
            a ? a = a.concat(r) : a = [r],
            a = this._filterPathPoint(a);
            let h = t
              , f = a.shift();
            if (!f)
                return l("[Engine input path error]");
            let d = calcDistance3D(h, f) / n;
            const _ = 1e3 / 25;
            e.rootNode.lookAt(ue4Position2Xverse(f));
            const g = xverseRotation2Ue4({
                x: e.rootNode.rotation.x,
                y: e.rootNode.rotation.y,
                z: e.rootNode.rotation.z
            });
            g && (g.roll = 0,
            g.pitch = 0,
            e.setRotation(g)),
            this._movingObserver && u.onBeforeRenderObservable.remove(this._movingObserver),
            (m = e.controller) == null || m.playAnimation(o, !0),
            this._movingObserver = u == null ? void 0 : u.onBeforeRenderObservable.add(()=>{
                var v;
                if (c < 1) {
                    const y = BABYLON.Vector3.Lerp(ue4Position2Xverse(h), ue4Position2Xverse(f), c);
                    if (e.setPosition(xversePosition2Ue4(y)),
                    !e.rootNode)
                        return e.setPosition(r),
                        s();
                    c += _ / (d * 1e3)
                } else if (h = f,
                f = a.shift(),
                f) {
                    d = calcDistance3D(h, f) / n,
                    e.rootNode.lookAt(ue4Position2Xverse(f));
                    const y = xverseRotation2Ue4({
                        x: e.rootNode.rotation.x,
                        y: e.rootNode.rotation.y,
                        z: e.rootNode.rotation.z
                    });
                    y && (y.roll = 0,
                    y.pitch = 0,
                    e.setRotation(y)),
                    c = 0
                } else
                    return u.onBeforeRenderObservable.remove(this._movingObserver),
                    (v = e.controller) == null || v.playAnimation("Idle", !0),
                    s()
            }
            )
        }
        )
    }
    lookAt(e, t, r) {
        return new Promise(n=>{
            var _, g;
            const o = ue4Position2Xverse(t)
              , s = e.rootNode.position.subtract(o).length()
              , l = new BABYLON.Vector3(s * Math.sin(e.rootNode.rotation.y),0,s * Math.cos(e.rootNode.rotation.y))
              , u = (_ = e.rootNode) == null ? void 0 : _.position.add(l);
            let c = 0;
            const h = r || 1 / 100
              , f = (g = e.rootNode) == null ? void 0 : g.getScene()
              , d = f == null ? void 0 : f.onBeforeRenderObservable.add(()=>{
                var y, b;
                const m = (y = e.controller) == null ? void 0 : y.animations.find(T=>T.name == "Idle");
                (m == null ? void 0 : m.isPlaying) != !0 && (m == null || m.play());
                const v = BABYLON.Vector3.Lerp(u, o, c);
                c < 1 ? ((b = e.rootNode) == null || b.lookAt(v),
                c += h) : (d && f.onBeforeRenderObservable.remove(d),
                n())
            }
            )
        }
        )
    }
    sendObjectTo(e, t, r, n=2, o=10, a={
        x: 0,
        y: 0,
        z: 150
    }) {
        return new Promise((s,l)=>{
            var u;
            if (!r.loaded)
                l("Gift has not inited!");
            else {
                const c = (u = e.rootNode) == null ? void 0 : u.getScene();
                let h = 0;
                const f = 1 / (n * 25)
                  , d = f
                  , _ = o / 100
                  , g = 8 * _ * f * f;
                let m = .5 * g / f
                  , v = ue4Position2Xverse(e.position);
                const y = ue4Position2Xverse(a)
                  , b = ue4Position2Xverse(e.position)
                  , T = c == null ? void 0 : c.onBeforeRenderObservable.add(()=>{
                    (!t || !e.position || !t.position) && (T && c.onBeforeRenderObservable.remove(T),
                    l("Invalid receiver when shoot gift!")),
                    r.loaded || (T && c.onBeforeRenderObservable.remove(T),
                    s());
                    const C = ue4Position2Xverse(t.position)
                      , A = new BABYLON.Vector3((C.x - b.x) * f,m,(C.z - b.z) * f);
                    m = m - g,
                    h < 1 ? (v = v.add(A),
                    r.setPositionVector(v.add(y)),
                    h += d) : (s(),
                    T && c.onBeforeRenderObservable.remove(T))
                }
                )
            }
        }
        )
    }
    roll(e, t, r, n) {
        var o, a;
        this._observer && ((o = this._scene) == null || o.onBeforeRenderObservable.remove(this._observer)),
        t && (r = r != null ? r : 1,
        n = n != null ? n : 1,
        this._observer = (a = this._scene) == null ? void 0 : a.onBeforeRenderObservable.add(()=>{
            e.rootNode.rotation.y += r * .1 * n,
            e.rootNode.rotation.y %= Math.PI * 2
        }
        ))
    }
    disposeObsever() {
        this._movingObserver && this._scene.onBeforeRenderObservable.remove(this._movingObserver)
    }
}