import { assert } from "../../assert.js";
import { aabb3_array_set } from "../../geom/3d/aabb/aabb3_array_set.js";

/**
 * A convenience class to work with BVH leaf nodes
 */
export class BvhClient {
    /**
     *
     * @type {BVH|null}
     */
    #tree = null;

    /**
     *
     * @type {number}
     */
    #node_id = -1;

    /**
     * @readonly
     * @type {number[]}
     */
    bounds = new Float32Array(6);

    get is_linked() {
        return this.#node_id !== -1;
    }

    /**
     *
     * @param {BVH} tree
     * @param {number} data Must be a uint32
     */
    link(tree, data) {
        assert.equal(this.is_linked, false, 'already linked');
        assert.defined(tree, 'tree');
        assert.isNonNegativeInteger(data, 'data');

        this.#tree = tree;

        const node_id = tree.allocate_node();

        this.#node_id = node_id;

        tree.node_set_aabb(node_id, this.bounds);
        tree.node_set_user_data(node_id, data);
        tree.insert_leaf(node_id);
    }

    unlink() {
        assert.equal(this.is_linked, true, 'not linked');

        const node_id = this.#node_id;

        this.#tree.remove_leaf(node_id);
        this.#tree.release_node(node_id);

        this.#node_id = -1;
        this.#tree = null;
    }

    write_bounds() {
        if (this.#tree === null) {
            // nothing to write to
            return;
        }

        this.#tree.node_move_aabb(this.#node_id, this.bounds);
    }

    /**
     *
     * @param {number} x0
     * @param {number} y0
     * @param {number} z0
     * @param {number} x1
     * @param {number} y1
     * @param {number} z1
     */
    resize(x0, y0, z0, x1, y1, z1) {
        aabb3_array_set(
            this.bounds, 0,
            x0, y0, z0, x1, y1, z1
        );

        this.write_bounds();
    }
}
