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

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

/**
 *
 * @template T
 * @param {Array<QuadTreeDatum<T>>} result
 * @param {number} result_offset
 * @param {QuadTreeNode<T>} tree
 * @param {number} x0
 * @param {number} y0
 * @param {number} x1
 * @param {number} y1
 * @returns {number}
 */
export function qt_collect_by_box(
    result, result_offset,
    tree,
    x0, y0,x1, y1
){
    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(x0, 'x0');
    assert.isNumber(y0, 'y0');
    assert.isNumber(x1, 'x1');
    assert.isNumber(y1, 'y1');

    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_overlap_exists(node.x0, node.y0, node.x1, node.y1, x0, y0, x1,y1)) {
            // 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_overlap_exists(datum.x0, datum.y0, datum.x1, datum.y1, x0, y0, x1,y1)) {
                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 >= x0) {
                if (hy >= y0) {
                    node_stack[stack_pointer++] = node.topLeft;
                }
                if (hy <= y1) {
                    node_stack[stack_pointer++] = node.bottomLeft;
                }
            }

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


        }
    }

    return result_cursor - result_offset;
}