import { AppObjectUC, getSingletonComponent, } from "@vived/core";
import { ParametricPlane, Quaternion, Vector2, Vector3 } from "@vived/core";
import { pixelToSceneRay } from "../../Babylon";
import { MouseInputEntity } from "../../MouseInput";
import { TouchInputEntity } from "../../TouchController";
import { StylusEntity } from "../Entity/StylusEntity";
export class EmulateStylusUC extends AppObjectUC {
    static get(appObjects) {
        return getSingletonComponent(EmulateStylusUC.type, appObjects);
    }
}
EmulateStylusUC.type = "EmulateStylusUC";
export function makeEmulateStylusUC(appObject) {
    return new EmulateStylusUCImp(appObject);
}
class EmulateStylusUCImp extends EmulateStylusUC {
    get mouseInput() {
        return this.getCachedSingleton(MouseInputEntity.type);
    }
    get touchInput() {
        return this.getCachedSingleton(TouchInputEntity.type);
    }
    get stylus() {
        return this.getCachedSingleton(StylusEntity.type);
    }
    get isEmulating() {
        return this._isEmulating;
    }
    constructor(appObject) {
        super(appObject, EmulateStylusUC.type);
        this._eventElement = undefined;
        this.lastMousePos = Vector2.Zero();
        this._isEmulating = false;
        this.screenPlane = ParametricPlane.FromPointNormal(Vector3.Zero(), Vector3.Backward());
        this.startEmulating = () => {
            if (!this.mouseInput)
                return;
            if (!this.stylus)
                return;
            if (this._isEmulating === true)
                return;
            this._eventElement = this.mouseInput.eventElement;
            if (!this._eventElement) {
                this.warn("No event element");
                return;
            }
            this.mouseInput.clearInputElement();
            this.touchInput?.clearInputElement();
            this._eventElement.addEventListener("mousedown", this.onMouseDown, false);
            this._eventElement.addEventListener("mouseup", this.onMouseUp, false);
            this._eventElement.addEventListener("mousemove", this.onMouseMove, false);
            this._eventElement.addEventListener("keydown", this.submitKeyDown, false);
            this.stylus.transform.localPosition = new Vector3(0.05, -0.05, -0.5);
            this._isEmulating = true;
        };
        this.stopEmulating = () => {
            if (!this.mouseInput)
                return;
            if (this._isEmulating === false)
                return;
            if (this._eventElement) {
                this._eventElement.removeEventListener("mousedown", this.onMouseDown, false);
                this._eventElement.removeEventListener("mouseup", this.onMouseUp, false);
                this._eventElement.removeEventListener("mousemove", this.onMouseMove, false);
                this._eventElement.removeEventListener("keydown", this.submitKeyDown, false);
                this.mouseInput.setEventElement(this._eventElement);
                this.touchInput?.setEventElement(this._eventElement);
            }
            this._eventElement = undefined;
            this._isEmulating = false;
        };
        this.submitKeyDown = (e) => {
            const bumpAmount = 0.01;
            let bump = Vector3.Zero();
            switch (e.code) {
                case "KeyA":
                    bump = new Vector3(-bumpAmount, 0, 0);
                    break;
                case "KeyD":
                    bump = new Vector3(bumpAmount, 0, 0);
                    break;
                case "KeyW":
                    bump = new Vector3(0, 0, bumpAmount);
                    break;
                case "KeyS":
                    bump = new Vector3(0, 0, -bumpAmount);
                    break;
            }
            if (!this.stylus)
                return;
            const currentPos = this.stylus.transform.localPosition;
            this.stylus.transform.localPosition = Vector3.Add(currentPos, bump);
            this.pointAtMouse(this.lastMousePos);
        };
        this.onMouseDown = (e) => {
            if (!this.stylus)
                return;
            this.stylus.updateButtonState(e.button, true);
        };
        this.onMouseUp = (e) => {
            if (!this.stylus)
                return;
            this.stylus.updateButtonState(e.button, false);
        };
        this.onMouseMove = (e) => {
            const px = e.offsetX;
            const py = e.offsetY;
            const pos = new Vector2(px, py);
            this.pointAtMouse(pos);
            this.lastMousePos = pos;
        };
        this.pointAtMouse = (pos) => {
            if (!this.stylus)
                return;
            const ray = pixelToSceneRay(pos, this.appObjects);
            const hit = this.screenPlane.intersectLine(ray);
            if (!hit) {
                return;
            }
            const direction = Vector3.Subtract(hit, this.stylus.transform.localPosition);
            this.stylus.transform.localRotation = Quaternion.FromDirectionVector(direction);
        };
        this.appObjects.registerSingleton(this);
    }
}
//# sourceMappingURL=EmulateStylusUC.js.map