class Node:
    def __init__(self, name=None, parent=None, available=True):
        self.name = name
        self.parent = parent
        self.available = available
        self.children = []

    @property
    def next_sibling(self):
        """Return next node on the same level."""
        try:
            return self.parent.children[self.parent.children.index(self)+1]
        except (AttributeError, IndexError):
            return None

    def next_node(self):
        if self.available:
            if self.children:
                if not self.children[0].available:
                    return self.children[0].next_node()
                else:
                    return self.children[0]
            elif self.parent is not None:
                node = self
                while True:
                    if node.parent is not None:
                        node = node.parent
                        if node.next_sibling:
                            if not node.next_sibling.available:
                                return node.next_sibling.next_node()
                            else:
                                return node.next_sibling
                    else:
                        break
        else:
            if self.next_sibling:
                if not self.next_sibling.available:
                    return self.next_sibling.next_node()
                else:
                    return self.next_sibling
            elif self.parent is not None:
                if self.parent.next_sibling:
                    if not self.parent.next_sibling.available:
                        return self.parent.next_sibling.next_node()
                    else:
                        return self.parent.next_sibling
        return None


def print_tree(node, only_available=False):
    todo = [node]
    while todo:
        node = todo.pop()      
        if only_available and not node.available:
            continue
        todo.extend(reversed(node.children))
        print(node.name + (' (unavailable)' if not node.available else ''))


def traverse(node):
    while True:
        print(node.name)
        node = node.next_node()
        if not node:
            break


grandparent = Node(name='grandparent')
parent0 = Node(name='    parent0', parent=grandparent)
parent1 = Node(name='    parent1', parent=grandparent)
parent2 = Node(name='    parent2', parent=grandparent, available=False)
parent3 = Node(name='    parent3', parent=grandparent)
child0 = Node(name='        child0', parent=parent0, available=False)
child1 = Node(name='        child1', parent=parent0, available=False)
child2 = Node(name='        child2', parent=parent1, available=False)
child3 = Node(name='        child3', parent=parent1)
child4 = Node(name='        child4', parent=parent2)
child5 = Node(name='        child5', parent=parent3)
child6 = Node(name='        child6', parent=parent3, available=False)
grandchild0 = Node(name='            grandchild0', parent=child0)
grandchild1 = Node(name='            grandchild1', parent=child0)
grandchild2 = Node(name='            grandchild2', parent=child3)
grandparent.children = [parent0, parent1, parent2, parent3]
parent0.children = [child0, child1]
parent1.children = [child2, child3]
parent2.children = [child4]
parent3.children = [child5, child6]
child0.children = [grandchild0, grandchild1]
child3.children = [grandchild2]
print('Full node tree:\n')
print_tree(grandparent, only_available=False)
print('\n\nGoal sequence:\n')
print_tree(grandparent, only_available=True)
print('\n\nTraverse using Node.next_node() method (must be equal to "Goal sequence"):\n')
traverse(grandparent)