import { assert } from "../../../../core/assert.js";

/**
 *
 * @param {Behavior|CompositeBehavior|AbstractDecoratorBehavior} root
 * @param {function(Behavior):boolean?} visitor
 * @param {*} [thisArg]
 */
export function behavior_traverse_tree(root, visitor, thisArg) {

    assert.defined(root, 'root');
    assert.notNull(root, 'root');
    assert.equal(root.isBehavior, true, 'root.isBehavior !== true');

    assert.isFunction(visitor, 'visitor');

    const should_continue = visitor.call(thisArg, root);

    if (should_continue === false) {
        // terminate traversal
        return;
    }

    if (root.isCompositeBehavior === true) {

        const children = root.children;

        const child_count = children.length;

        for (let i = 0; i < child_count; i++) {
            const child = children[i];

            behavior_traverse_tree(child, visitor, thisArg);
        }
    }

    if (root.isDecoratorBehavior === true) {

        const source = root.getSource();
        behavior_traverse_tree(source, visitor, thisArg);
    }

}
