package me.eater.threedom.dom

interface INodeContainer : INodeQueryCapable {
    /**
     * Add node to this node container
     */
    fun addNode(newNode: INode<*>)

    /**
     * Remove node from this node container
     */
    fun removeNode(refNode: INode<*>)

    /**
     * Remove all nodes from this node container
     */
    fun removeAll()

    /**
     * Replace [newNode] with [refNode], if [newNode] is not part of this node, [refNode] will not be added
     */
    fun replaceNode(newNode: INode<*>, refNode: INode<*>): Boolean

    /**
     * Check if [refNode] is a child from this node
     */
    fun hasChild(refNode: INode<*>): Boolean

    /**
     * Return a sequence of (direct) child nodes
     */
    fun sequence(): Sequence<INode<*>>

    operator fun iterator(): Iterator<INode<*>>

    /**
     * Return a recursive iterator which will iterate over all children, and their children etc.
     */
    fun recursiveIterator(): Iterator<INode<*>> = sequence<INode<*>> {
        val iterators = mutableListOf<Iterator<INode<*>>>()
        var current: Iterator<INode<*>>? = iterator()
        while (current != null) {

            for (node in current) {
                yield(node)
                iterators.add(node.iterator())
            }

            current = iterators.firstOrNull()?.apply { iterators.removeAt(0) }
        }
    }.iterator()
}
