class_name NodeExt
extends Object

class NodeChildIterator:
    var _node: Node
    var _include_internal: bool
    var _index: int
    var _length: int

    func _init(node: Node, include_internal: bool) -> void:
        _node = node
        _include_internal = include_internal
        _index = 0
        _length = node.get_child_count(include_internal)

    func _continue() -> bool:
        return (_index < _length)

    func _iter_init(_iter: Array) -> bool:
        _index = 0
        return _continue()

    func _iter_next(_iter: Array) -> bool:
        _index += 1
        return _continue()

    func _iter_get(_iter: Variant) -> Variant:
        return _node.get_child(_index, _include_internal)

static func find_child(node: Node, predicate: Callable, include_internal: bool = false) -> Option:
    for child in NodeChildIterator.new(node, include_internal):
        if predicate.call(child):
            return Option.some(child)
    return Option.none

static func find_child_variant(node: Node, variant: Variant, include_internal: bool = false) -> Option:
    for child in NodeChildIterator.new(node, include_internal):
        if is_instance_of(child, variant):
            return Option.some(child)
    return Option.none
