export class VirtualTouchJoystick {
    initialCenter;
    radius;
    deadZone;
    maxDistance;
    fixed;
    returnToCenter;
    centerRef;
    stickRef;
    valueRef = [0, 0];
    activeTouchId = null;
    active = false;
    consumedTouches = 0;
    constructor(config) {
        this.initialCenter = config.center;
        this.centerRef = config.center;
        this.stickRef = config.center;
        this.radius = positive(config.radius, 64);
        this.deadZone = clamp(config.deadZone ?? 0.15, 0, 0.95);
        this.maxDistance = positive(config.maxDistance, this.radius * 0.8);
        this.fixed = config.fixed ?? true;
        this.returnToCenter = config.returnToCenter ?? true;
    }
    touchStart(touch) {
        if (this.activeTouchId !== null)
            return false;
        if (distance([touch.x, touch.y], this.centerRef) > this.radius)
            return false;
        this.activeTouchId = touch.id;
        this.active = true;
        this.consumedTouches += 1;
        if (!this.fixed)
            this.centerRef = [touch.x, touch.y];
        this.updateStick([touch.x, touch.y]);
        return true;
    }
    touchMove(touch) {
        if (touch.id !== this.activeTouchId)
            return false;
        this.updateStick([touch.x, touch.y]);
        return true;
    }
    touchEnd(touch) {
        if (touch.id !== this.activeTouchId)
            return false;
        this.activeTouchId = null;
        this.active = false;
        if (this.returnToCenter) {
            this.stickRef = this.centerRef;
            this.valueRef = [0, 0];
        }
        if (!this.fixed)
            this.centerRef = this.initialCenter;
        return true;
    }
    snapshot() {
        return {
            source: "origin-master-touch-joystick-virtual-input-adapted",
            active: this.active,
            activeTouchId: this.activeTouchId,
            center: [round(this.centerRef[0]), round(this.centerRef[1])],
            stick: [round(this.stickRef[0]), round(this.stickRef[1])],
            value: [round(this.valueRef[0]), round(this.valueRef[1])],
            magnitude: round(Math.hypot(this.valueRef[0], this.valueRef[1])),
            deadZone: this.deadZone,
            consumedTouches: this.consumedTouches,
            evidence: {
                oldCodebasePort: true,
                virtualJoystick: true,
                deadZone: true,
                clampedMagnitude: Math.hypot(this.valueRef[0], this.valueRef[1]) <= 1.0001,
                returnToCenter: this.returnToCenter,
                floatingCenter: !this.fixed
            }
        };
    }
    updateStick(touch) {
        const dx = touch[0] - this.centerRef[0];
        const dy = touch[1] - this.centerRef[1];
        const rawDistance = Math.hypot(dx, dy);
        if (rawDistance === 0) {
            this.stickRef = this.centerRef;
            this.valueRef = [0, 0];
            return;
        }
        const clampedDistance = Math.min(rawDistance, this.maxDistance);
        const nx = dx / rawDistance;
        const ny = dy / rawDistance;
        this.stickRef = [this.centerRef[0] + nx * clampedDistance, this.centerRef[1] + ny * clampedDistance];
        const normalized = clampedDistance / this.maxDistance;
        if (normalized < this.deadZone) {
            this.valueRef = [0, 0];
            return;
        }
        const remapped = Math.min(1, (normalized - this.deadZone) / (1 - this.deadZone));
        this.valueRef = [nx * remapped, ny * remapped];
    }
}
export function sampleVirtualTouchJoystickFixture() {
    const joystick = new VirtualTouchJoystick({
        center: [96, 420],
        radius: 72,
        deadZone: 0.2,
        maxDistance: 56,
        fixed: false,
        returnToCenter: true
    });
    joystick.touchStart({ id: 7, x: 90, y: 416 });
    joystick.touchMove({ id: 7, x: 154, y: 376 });
    const active = joystick.snapshot();
    joystick.touchEnd({ id: 7, x: 154, y: 376 });
    return { active, released: joystick.snapshot() };
}
function positive(value, fallback) {
    const number = Number(value);
    return Number.isFinite(number) && number > 0 ? number : fallback;
}
function distance(a, b) {
    return Math.hypot(a[0] - b[0], a[1] - b[1]);
}
function clamp(value, min, max) {
    return Math.max(min, Math.min(max, value));
}
function round(value) {
    return Number(value.toFixed(4));
}
//# sourceMappingURL=VirtualTouchControls.js.map