/**
 * Ambient types for box3d-wasm@0.2.0, which ships no `.d.ts`.
 *
 * Written against the runtime API as actually exposed by the embind bindings
 * (verified by enumerating prototypes on the built wasm module), not from the
 * README — the README documents a slightly larger surface than is bound.
 *
 * Notably ABSENT from the binding, contrary to the design doc:
 *   - no character mover / controller (see `systems/CharacterMover.ts`)
 *   - no triangle-mesh shape (rooms are box/hull compounds)
 *   - no shape casting or overlap queries (only ray casts)
 */
declare module "box3d-wasm" {
  export interface B3Vec3 {
    x: number;
    y: number;
    z: number;
  }

  export interface B3Quat {
    x: number;
    y: number;
    z: number;
    w: number;
  }

  export interface B3Transform {
    position: B3Vec3;
    rotation: B3Quat;
  }

  export interface B3Filter {
    categoryBits?: number;
    maskBits?: number;
    groupIndex?: number;
  }

  export interface B3RayResult {
    hit: boolean;
    point: B3Vec3;
    normal: B3Vec3;
    fraction: number;
    shapeUserData: number;
    bodyUserData: number;
    shape: B3Shape;
  }

  export interface B3ShapeOptionsBase {
    density?: number;
    friction?: number;
    restitution?: number;
    isSensor?: boolean;
    filter?: B3Filter;
    userData?: number;
    enableContactEvents?: boolean;
    enableSensorEvents?: boolean;
    enableHitEvents?: boolean;
  }

  export interface B3BoxOptions extends B3ShapeOptionsBase {
    halfExtents: B3Vec3;
    center?: B3Vec3;
    rotation?: B3Quat;
  }

  export interface B3SphereOptions extends B3ShapeOptionsBase {
    radius: number;
    center?: B3Vec3;
  }

  export interface B3CapsuleOptions extends B3ShapeOptionsBase {
    radius: number;
    height: number;
    center?: B3Vec3;
    rotation?: B3Quat;
  }

  export interface B3HullOptions extends B3ShapeOptionsBase {
    points: B3Vec3[];
  }

  export class B3Shape {
    getType(): string;
    getUserData(): number;
    setUserData(tag: number): void;
    getAABB(): { lowerBound: B3Vec3; upperBound: B3Vec3 };
    getFilter(): Required<B3Filter>;
    setFilter(filter: B3Filter): void;
    getFriction(): number;
    setFriction(friction: number): void;
    getRestitution(): number;
    setRestitution(restitution: number): void;
    getDensity(): number;
    setDensity(density: number): void;
    isSensor(): boolean;
    isValid(): boolean;
    rayCast(origin: B3Vec3, translation: B3Vec3): B3RayResult;
    enableContactEvents(enable: boolean): void;
    enableSensorEvents(enable: boolean): void;
    enableHitEvents(enable: boolean): void;
    destroy(): void;
    delete(): void;
  }

  export type B3BodyType = "static" | "kinematic" | "dynamic";

  export interface B3BodyOptions {
    type?: B3BodyType;
    position?: B3Vec3;
    rotation?: B3Quat;
    linearVelocity?: B3Vec3;
    angularVelocity?: B3Vec3;
    linearDamping?: number;
    angularDamping?: number;
    gravityScale?: number;
    enableSleep?: boolean;
    isAwake?: boolean;
    isEnabled?: boolean;
    isBullet?: boolean;
    userData?: number;
    name?: string;
    motionLocks?: {
      linearX?: boolean;
      linearY?: boolean;
      linearZ?: boolean;
      angularX?: boolean;
      angularY?: boolean;
      angularZ?: boolean;
    };
  }

  export class B3Body {
    createBox(options: B3BoxOptions): B3Shape;
    createSphere(options: B3SphereOptions): B3Shape;
    createCapsule(options: B3CapsuleOptions): B3Shape;
    createHull(options: B3HullOptions): B3Shape;

    getPosition(): B3Vec3;
    getRotation(): B3Quat;
    getTransform(): B3Transform;
    setTransform(transform: B3Transform): void;
    /** Kinematic drive: moves the body to `transform` over `dt`, deriving velocity. */
    setTargetTransform(transform: B3Transform, dt: number): void;

    getLinearVelocity(): B3Vec3;
    setLinearVelocity(v: B3Vec3): void;
    getAngularVelocity(): B3Vec3;
    setAngularVelocity(v: B3Vec3): void;

    applyForce(force: B3Vec3, worldPoint: B3Vec3, wake: boolean): void;
    applyForceToCenter(force: B3Vec3, wake: boolean): void;
    applyLinearImpulse(impulse: B3Vec3, worldPoint: B3Vec3, wake: boolean): void;
    applyLinearImpulseToCenter(impulse: B3Vec3, wake: boolean): void;
    applyTorque(torque: B3Vec3, wake: boolean): void;
    applyAngularImpulse(impulse: B3Vec3, wake: boolean): void;
    applyMassFromShapes(): void;

    getMass(): number;
    getType(): B3BodyType;
    setType(type: B3BodyType): void;
    getUserData(): number;
    setUserData(tag: number): void;
    getName(): string;
    setName(name: string): void;
    getShapeCount(): number;
    computeAABB(): { lowerBound: B3Vec3; upperBound: B3Vec3 };
    getWorldPoint(local: B3Vec3): B3Vec3;
    getLocalPoint(world: B3Vec3): B3Vec3;
    getWorldCenterOfMass(): B3Vec3;
    getLocalCenterOfMass(): B3Vec3;
    getMotionLocks(): Record<string, boolean>;
    setMotionLocks(locks: B3BodyOptions["motionLocks"]): void;
    getLinearDamping(): number;
    setLinearDamping(d: number): void;
    getAngularDamping(): number;
    setAngularDamping(d: number): void;
    getGravityScale(): number;
    setGravityScale(s: number): void;
    isAwake(): boolean;
    setAwake(awake: boolean): void;
    enableSleep(enable: boolean): void;
    isEnabled(): boolean;
    setEnabled(enabled: boolean): void;
    isBullet(): boolean;
    setBullet(bullet: boolean): void;
    isValid(): boolean;
    destroy(): void;
    delete(): void;
  }

  export interface B3SensorEvent {
    sensorUserData: number;
    visitorUserData: number;
  }

  export interface B3ContactEvent {
    shapeUserDataA: number;
    shapeUserDataB: number;
    point?: B3Vec3;
    normal?: B3Vec3;
    approachSpeed?: number;
  }

  export interface B3BodyEvent {
    userData: number;
    position: B3Vec3;
    rotation: B3Quat;
    fellAsleep: boolean;
  }

  export interface B3WorldOptions {
    gravity?: B3Vec3;
    enableSleep?: boolean;
    enableContinuous?: boolean;
    /** Deluxe (threaded) build only; clamped to [1, maxWorkers]. */
    workerCount?: number;
  }

  export class B3World {
    constructor(options?: B3WorldOptions);
    step(timeStep: number, subStepCount: number): void;
    createBody(options?: B3BodyOptions): B3Body;
    castRayClosest(origin: B3Vec3, translation: B3Vec3, filter?: B3Filter): B3RayResult;
    explode(options: {
      position: B3Vec3;
      radius: number;
      falloff?: number;
      impulsePerArea?: number;
    }): void;
    getGravity(): B3Vec3;
    setGravity(gravity: B3Vec3): void;
    getAwakeBodyCount(): number;
    getWorkerCount(): number;
    getProfile(): Record<string, number>;
    getBodyEvents(): B3BodyEvent[];
    getContactEvents(): { begin: B3ContactEvent[]; end: B3ContactEvent[]; hit: B3ContactEvent[] };
    getSensorEvents(): { begin: B3SensorEvent[]; end: B3SensorEvent[] };
    enableSleeping(enable: boolean): void;
    enableContinuous(enable: boolean): void;
    isValid(): boolean;
    destroy(): void;
    delete(): void;

    createDistanceJoint(a: B3Body, b: B3Body, options?: object): unknown;
    createRevoluteJoint(a: B3Body, b: B3Body, options?: object): unknown;
    createSphericalJoint(a: B3Body, b: B3Body, options?: object): unknown;
    createPrismaticJoint(a: B3Body, b: B3Body, options?: object): unknown;
    createWeldJoint(a: B3Body, b: B3Body, options?: object): unknown;
    createMotorJoint(a: B3Body, b: B3Body, options?: object): unknown;
    createWheelJoint(a: B3Body, b: B3Body, options?: object): unknown;
    createParallelJoint(a: B3Body, b: B3Body, options?: object): unknown;
    createFilterJoint(a: B3Body, b: B3Body, options?: object): unknown;
  }

  export interface Box3DModule {
    World: typeof B3World;
    Body: typeof B3Body;
    Shape: typeof B3Shape;
    /** True when the threaded "deluxe" build was loaded. */
    threaded: boolean;
    maxWorkers: number;
    HEAPF32: Float32Array;
    HEAPU32: Uint32Array;
    HEAPU8: Uint8Array;
  }

  const Box3D: () => Promise<Box3DModule>;
  export default Box3D;
}

declare module "box3d-wasm/standard" {
  export { default } from "box3d-wasm";
}

declare module "box3d-wasm/deluxe" {
  export { default } from "box3d-wasm";
}
