import E from './engine.c';

namespace Physics {
    const TYPE_CIRCLE = 1;
    const TYPE_PLANE = 2;

    export function newCircle(x: number, y: number, radius: number, mass: number = 1.0): number {
        const body = E.rigid_body_new_circle(x, y, 0, 0, mass, radius);
        return body;
    }

    export function newPlane(x: number, y: number, nx: number, ny: number): number {
        const body = E.rigid_body_new_plane(x, y, nx, ny);
        return body;
    }

    export function deleteBody(body: number) {
        E.rigid_body_free(body);
    }

    export function addForce(body: number, fx: number, fy: number) {
        E.rigid_body_add_force(body, fx, fy);
    }

    export function addGlobalForce(fx: number, fy: number) {
        E.rigid_body_add_global_force(fx, fy);
    }

    export function update(dt: number) {
        E.rigid_body_update_all(dt);
    }

    export function getBody(idx: number) {
        const ptr = E.rigid_body_get(idx);
        const type = E.data.getUint8(ptr);

        const x = E.data.getFloat32(ptr + 4, true);
        const y = E.data.getFloat32(ptr + 8, true);

        const vx = E.data.getFloat32(ptr + 12, true);
        const vy = E.data.getFloat32(ptr + 16, true);
        const mass = E.data.getFloat32(ptr + 20, true);

        if (type === TYPE_CIRCLE) {
            const radius = E.data.getFloat32(ptr + 24, true);
            return { id: ptr, x, y, vx, vy, mass, radius };
        } else if (type === TYPE_PLANE) {
            const nx = E.data.getFloat32(ptr + 24, true);
            const ny = E.data.getFloat32(ptr + 28, true);
            return { id: ptr, type, x, y, vx, vy, mass, nx, ny };
        }

        return { id: ptr, type, x, y, vx, vy, mass };
    }

    export function setCollisionCallback(cb: (a: number, b: number) => void) {
        const cbPtr = E.table.grow(1, new WebAssembly.Function({ parameters: ['i32', 'i32'], results: [] }, cb));
        E.rigid_body_set_collision_callback(cbPtr);
    }
}

export default Physics;
