//const log$E = new Logger$1("Avatar")

import BillboardStatus from "./enum/BillboardStatus.js"
import {avatarLoader} from "./XAvatarLoader.js"
import XAnimationController from "./XAnimationController.js"
import XAvatarComopnent from "./XAvatarComopnent.js"
import XStateMachine from "./XStateMachine.js"
import XAvatarBillboardComponent from "./XAvatarBillboardComponent.js"

const castRayOffsetY = .01;
const castRayTeleportationOffset = 10;

export default class XAvatar {
    constructor({id: e, avatarType: t, priority: r, avatarManager: n, assets: o, status: a}) {
        E(this, "id", "-1");
        E(this, "priority", 0);
        E(this, "isRender", !1);
        E(this, "distLevel", 0);
        E(this, "isInLoadingList", !1);
        E(this, "isHide", !1);
        E(this, "component");
        E(this, "controller");
        E(this, "stateMachine");
        E(this, "bbComponent");
        E(this, "_avatarType");
        E(this, "clothesList", []);
        E(this, "isSelected", !1);
        E(this, "pendingLod", !1);
        E(this, "_previousReceivedPosition", new BABYLON.Vector3(0,1e4,0));
        E(this, "_avatarPosition");
        E(this, "_avatarRotation");
        E(this, "_avatarScale");
        E(this, "rootNode");
        E(this, "distToCam", 1e11);
        E(this, "enableNickname", !0);
        E(this, "distance", 1e11);
        E(this, "isCulling", !1);
        E(this, "reslevel", 0);
        E(this, "isInLoadingQueue", !1);
        E(this, "_isRayCastEnable");
        E(this, "_scene");
        E(this, "_avatarManager");
        E(this, "_transparent", 0);
        E(this, "hide", ()=>(this.isHide = !0,
        this._hide(),
        !this.isRender));
        E(this, "_show", ()=>{
            var e;
            this.isHide || (this.setIsPickable(!0),
            this.priority == 0 && (this.rootNode.setEnabled(!0),
            this.isRender = !0,
            this.avatarManager._updateBillboardStatus(this, BillboardStatus.SHOW),
            (e = this.controller) == null || e.playAnimation(this.controller.onPlay, this.controller.loop)))
        }
        );
        E(this, "show", ()=>(this.isHide = !1,
        this._show(),
        !!this.isRender));
        E(this, "setAnimations", e=>{
            this.controller.animations = e
        }
        );
        E(this, "attachToAvatar", (e,t=!1,r={
            x: 0,
            y: 0,
            z: 0
        },n=!1,o,a)=>this.bbComponent.attachToAvatar(this, e, t, r, n, o, a));
        E(this, "detachFromAvatar", (e,t=!1)=>this.bbComponent.detachFromAvatar(this, e, t));
        E(this, "getBbox", (e={})=>this.bbComponent.getBbox(this, e));
        this.id = e,
        this._avatarManager = n,
        this._scene = this.avatarManager.scene,
        this.clothesList = o,
        this._avatarType = t,
        this.priority = r || 0,
        this.controller = new XAnimationController(this),
        this.component = new XAvatarComopnent,
        this.stateMachine = new XStateMachine(this._scene),
        this.bbComponent = new XAvatarBillboardComponent(this._scene),
        this.rootNode = new BABYLON.TransformNode(e,this._avatarManager.scene),
        this._avatarScale = a.avatarScale == null ? 1 : a.avatarScale,
        this._avatarRotation = a.avatarRotation == null ? {
            pitch: 0,
            yaw: 0,
            roll: 0
        } : a.avatarRotation,
        this._avatarPosition = a.avatarPosition == null ? {
            x: 0,
            y: 0,
            z: 0
        } : a.avatarPosition,
        this.setPosition(this._avatarPosition),
        this.setRotation(this._avatarRotation),
        this.setScale(this.scale),
        this._isRayCastEnable = avatarSetting.isRayCastEnable,
        this._scene.registerBeforeRender(()=>{
            this.tick()
        }
        )
    }
    tick() {
        this.cullingTick()
    }
    cullingTick() {
        var e;
        this.isCulling && ((e = this.rootNode) == null || e.getChildMeshes().forEach(t=>{
            this.distToCam < 50 ? t.visibility = 0 : t.visibility = this._transparent
        }
        ))
    }
    setTransParentThresh(e) {
        this._transparent = e
    }
    get isNameVisible() {
        return this.bbComponent.isNameVisible
    }
    get isBubbleVisible() {
        return this.bbComponent.isBubbleVisible
    }
    get isGiftButtonsVisible() {
        return this.bbComponent.isGiftButtonsVisible
    }
    get words() {
        return this.bbComponent.words
    }
    get nickName() {
        return this.bbComponent.nickName
    }
    get giftButtons() {
        return this.bbComponent.giftButtons
    }
    get bubble() {
        return this.bbComponent.bubble
    }
    get nameBoard() {
        return this.bbComponent.nameBoard
    }
    get avatarManager() {
        return this._avatarManager
    }
    set withinVisibleRange(e) {
        this.bbComponent.withinVisualRange = e
    }
    setNicknameStatus(e) {
        return this.bbComponent.setNicknameStatus(e)
    }
    setBubbleStatus(e) {
        return this.bbComponent.setBubbleStatus(e)
    }
    setButtonsStatus(e) {
        return this.bbComponent.setBubbleStatus(e)
    }
    setGiftButtonsVisible(e) {
        return this.bbComponent.setGiftButtonsVisible(e)
    }
    get avatarType() {
        return this._avatarType
    }
    attachBody(e) {
        return this.component.addBodyComp(this, e)
    }
    attachDecoration(e) {
        return this.component.addClothesComp(this, e)
    }
    detachDecoration(e) {
        return this.component.clearClothesComp(e)
    }
    detachDecorationAll() {
        return this.component.clearAllClothesComps()
    }
    get skeleton() {
        return this.component.skeleton
    }
    get position() {
        return this._avatarPosition
    }
    get rotation() {
        return this._avatarRotation
    }
    get scale() {
        return this._avatarScale
    }
    _hide_culling() {
        this.bbComponent.updateBillboardStatus(this, BillboardStatus.HIDE),
        this.isCulling = !0
    }
    _show_culling() {
        this.isCulling && (this.rootNode && this.rootNode.getChildMeshes().forEach(e=>{
            e.visibility = 1
        }
        ),
        this.bbComponent.updateBillboardStatus(this, BillboardStatus.SHOW),
        this.isCulling = !1)
    }
    _hide() {
        !this.isHide || (this.setIsPickable(!1),
        this.priority == 0 ? (this.rootNode.setEnabled(!1),
        this.isRender = !1,
        this.bbComponent.updateBillboardStatus(this, BillboardStatus.HIDE)) : this.isRender && (this.avatarManager.currentLODUsers[this.distLevel]--,
        this.removeAvatarFromScene()))
    }
    rotate(e, t, r) {
        return this.stateMachine.roll(this, e, t, r)
    }
    set isRayCastEnable(e) {
        this._isRayCastEnable = e
    }
    get isRayCastEnable() {
        return this._isRayCastEnable
    }
    getAvatarId() {
        return this.id
    }
    getAvaliableAnimations() {
        const e = avatarLoader.avaliableAnimation.get(this.avatarType);
        return e || []
    }
    setPosition(e, t=!1) {
        if (this._avatarPosition = e,
        this.rootNode) {
            const r = ue4Position2Xverse(this._avatarPosition);
            let n = !1;
            this.avatarManager.getMainAvatar() && (this.id != this.avatarManager.getMainAvatar().id || (Math.abs(r.y - this._previousReceivedPosition.y) > castRayOffsetY && (n = !0),
            r.subtract(this._previousReceivedPosition).length() > castRayTeleportationOffset && (n = !0))),
            this._isRayCastEnable ? n || t ? this._castRay(e).then(o=>{
                this.rootNode.position = r,
                this.rootNode.position.y -= o
            }
            ).catch(o=>{
                Promise.reject(o)
            }
            ) : (this.rootNode.position.x = r.x,
            this.rootNode.position.z = r.z) : this.rootNode.position = r,
            this._previousReceivedPosition = r.clone()
        }
        return Promise.resolve(e)
    }
    setRotation(e) {
        if (this._avatarRotation = e,
        this.rootNode) {
            const t = {
                pitch: e.pitch,
                yaw: e.yaw + 180,
                roll: e.roll
            }
              , r = ue4Rotation2Xverse(t);
            this.rootNode.rotation = r
        }
    }
    setAvatarVisible(e) {
        this.rootNode && (this.rootNode.setEnabled(e),
        this.rootNode.getChildMeshes().forEach(t=>{
            t.setEnabled(e)
        }
        ))
    }
    setScale(e) {
        this._avatarScale = e,
        this.rootNode && (this.rootNode.scaling = new BABYLON.Vector3(e,e,e)),
        this.bbComponent.bbox && this.getBbox()
    }
    _removeAvatarFromScene() {
        var e, t;
        this.isRender = !1,
        (e = this.controller) == null || e.detachAnimation(),
        this.component.dispose(this),
        (t = this.avatarManager.sceneManager) == null || t.lightComponent.removeShadow(this)
    }
    removeAvatarFromScene() {
        this._removeAvatarFromScene(),
        this._disposeBillBoard()
    }
    _disposeBillBoard() {
        this.bbComponent.disposeBillBoard(this)
    }
    addComponent(e, t, r, n) {
        return this.component.changeClothesComp(this, e, t, r, n)
    }
    _castRay(e) {
        return new Promise((t,r)=>{
            var d;
            const n = ue4Position2Xverse(e)
              , o = new BABYLON.Vector3(0,-1,0)
              , a = 1.5 * this.scale
              , s = 100 * a
              , l = a
              , u = new BABYLON.Vector3(n.x,n.y + l,+n.z)
              , c = new BABYLON.Ray(u,o,s)
              , h = (d = this.avatarManager.sceneManager) == null ? void 0 : d.getGround(e);
            if (!h || h.length <= 0)
                return logger.warn(`\u89D2\u8272 id= ${this.id} \u627E\u4E0D\u5230\u5730\u9762\uFF0C\u5F53\u524D\u9AD8\u5EA6\u4E3A\u4E0B\u53D1\u9AD8\u5EA6`),
                t(0);
            let f = c.intersectsMeshes(h);
            if (f.length > 0)
                return t(f[0].distance - l);
            if (o.y = 1,
            f = c.intersectsMeshes(h),
            f.length > 0)
                return t(-(f[0].distance - l))
        }
        )
    }
    setPickBoxScale(e) {
        return this.bbComponent.setPickBoxScale(e)
    }
    setIsPickable(e) {
        return this.bbComponent.setIsPickable(this, e)
    }
    createPickBoundingbox(e) {
        return this.bbComponent.createPickBoundingbox(this, e)
    }
    scaleBbox(e) {
        this.bbComponent.bbox && this.bbComponent.bbox.scale(e)
    }
    rotateTo(e, t, r) {
        return this.stateMachine.rotateTo(this, e, t, r)
    }
    faceTo(e, t) {
        return this.stateMachine.lookAt(this, e, t)
    }
    removeObserver() {
        this.stateMachine.disposeObsever()
    }
    move(e, t, r, n, o) {
        return this.stateMachine.moveTo(this, e, t, r, n, o)
    }
    initNameboard(e=1) {
        return this.bbComponent.initNameboard(this, e)
    }
    initBubble(e=1) {
        return this.bbComponent.initBubble(this, e)
    }
    say(e, {id: t, isUser: r, background: n, font: o="Arial", fontsize: a=38, fontcolor: s="#ffffff", fontstyle: l="bold", linesize: u=22, linelimit: c, offsets: h={
        x: 0,
        y: 0,
        z: 40
    }, scale: f=this._avatarScale, compensationZ: d=11.2, reregistAnyway: _=!0}) {
        return this.bbComponent.say(this, e, {
            id: t,
            isUser: r,
            background: n,
            font: o,
            fontsize: a,
            fontcolor: s,
            fontstyle: l,
            linesize: u,
            linelimit: c,
            offsets: h,
            scale: f,
            compensationZ: d,
            reregistAnyway: _
        })
    }
    silent() {
        return this.bbComponent.silent()
    }
    setNickName(e, {id: t, isUser: r, background: n, font: o="Arial", fontsize: a=40, fontcolor: s="#ffffff", fontstyle: l="bold", linesize: u=22, linelimit: c, offsets: h={
        x: 0,
        y: 0,
        z: 15
    }, scale: f=this._avatarScale, compensationZ: d=0, reregistAnyway: _=!1}) {
        return this.bbComponent.setNickName(this, e, {
            id: t,
            isUser: r,
            background: n,
            font: o,
            fontsize: a,
            fontcolor: s,
            fontstyle: l,
            linesize: u,
            linelimit: c,
            offsets: h,
            scale: f,
            compensationZ: d,
            reregistAnyway: _
        })
    }
    generateButtons(e=null, t=this._avatarScale, r=85) {
        return this.bbComponent.generateButtons(this, e, t, r)
    }
    clearButtons() {
        return this.bbComponent.clearButtons()
    }
    attachExtraProp(e, t, r, n) {
        return this.component.addDecoComp(this, e, t, r, n)
    }
    showExtra(e) {
        return this.component.showExtra(e)
    }
    hideExtra(e) {
        return this.component.hideExtra(e)
    }
    disposeExtra() {
        return this.component.disposeExtra()
    }
    getSkeletonPositionByName(e) {
        var t;
        if (this.skeleton) {
            const r = this.skeleton.bones.find(n=>n.name.replace("Clone of ", "") == e);
            if (r && r.getTransformNode() && ((t = r.getTransformNode()) == null ? void 0 : t.position)) {
                const n = r.getTransformNode().position;
                return xversePosition2Ue4({
                    x: n.x,
                    y: n.y,
                    z: n.z
                })
            }
        }
    }
    shootTo(e, t, r=2, n=10, o={
        x: 0,
        y: 0,
        z: 150
    }) {
        return this.stateMachine.sendObjectTo(this, e, t, r, n, o)
    }
}