import { assert } from "../../../assert.js";
import { aabb2_intersects_point } from "../aabb/aabb2_intersects_point.js";

/**
 *
 * @type {QuadTreeNode[]}
 */
const node_stack = [];

/**
 * @template T
 * @param {Array<QuadTreeDatum<T>>} result
 * @param {number} result_offset
 * @param {QuadTreeNode<T>} tree
 * @param {number} x
 * @param {number} y
 * @returns {number}
 */
export function qt_collect_by_point(
    result, result_offset,
    tree,
    x, y
) {
    assert.isArray(result, 'result');
    assert.isNonNegativeInteger(result_offset, 'result_offset');
    assert.defined(tree, 'tree');
    assert.notNull(tree, 'tree');
    assert.equal(tree.isQuadTreeNode, true, 'tree.isQuadTreeNode !== true');
    assert.isNumber(x, 'x');
    assert.isNumber(y, 'y');

    let result_cursor = result_offset;

    let stack_pointer = 1;

    node_stack[0] = tree;

    while (stack_pointer-- > 0) {

        const node = node_stack[stack_pointer];

        if (!aabb2_intersects_point(node.x0, node.y0, node.x1, node.y1, x, y)) {
            // not a match
            continue;
        }

        const data = node.data;
        const data_count = data.length;

        for (let i = 0; i < data_count; i++) {
            const datum = data[i];

            if (aabb2_intersects_point(datum.x0, datum.y0, datum.x1, datum.y1, x, y)) {
                result[result_cursor++] = datum;
            }
        }

        if (node.isSplit()) {
            const hx = (node.x0 + node.x1) * 0.5;
            const hy = (node.y0 + node.y1) * 0.5;

            if (hx >= x) {
                if (hy >= y) {
                    node_stack[stack_pointer++] = node.topLeft;
                }
                if (hy <= y) {
                    node_stack[stack_pointer++] = node.bottomLeft;
                }
            }

            if (hx <= x) {
                if (hy >= y) {
                    node_stack[stack_pointer++] = node.topRight;
                }
                if (hy <= y) {
                    node_stack[stack_pointer++] = node.bottomRight;
                }
            }


        }
    }

    return result_cursor - result_offset;
}
