__author__ = 'Timothée DECOSTER'
__date_creation__ = 'Nov 15 18:37:07 2020'
__doc__ = """
:mod:`binary_tree` module
:author: {:s} 
:creation date: {:s}

>>> t1 = BinaryTree()
>>> t1.is_empty()
True
>>> t2 = BinaryTree(1, t1, t1)
>>> t2.is_empty()
False
>>> t2.get_data()
1
>>> t2.get_left_subtree().is_empty()
True
>>> t2.get_right_subtree().is_empty()
True
>>> t2.is_leaf()
True
>>> print(t2)
(1, (), ())
""".format(__author__, __date_creation__)


class BinaryTreeError(Exception):
    def __init__(self, msg):
        self.message = msg


class BinaryTree():
    def __init__(self, *args):
        """
        Binarytree Constructor

        :param args: any, BinaryTree , BinaryTree (optional) (Node, Left Child Tree, Right Child Tree )
        """
        if len(args) == 0:
            self.__content = None
        elif len(args) != 3:
            raise BinaryTreeError('bad arguments number for binary tree building')
        elif not isinstance(args[1], BinaryTree) or not isinstance(args[2], BinaryTree):
            raise BinaryTreeError('bad arguments type for binary tree building')
        else:
            self.__content = (args[0], args[1], args[2])

    def is_empty(self):
        """
        :return: (bool) True iff this tree is empty
        """
        return self.__content is None
        
    def get_data(self):
        """
        :return: (any) Value saved in the root node
        """
        try:
            return self.__content[0]
        except TypeError:
            raise BinaryTreeError('empty tree has no root')

    def get_left_subtree(self):
        """
        :return: (BinaryTree) Left Child Subtree
        """
        try:
            return self.__content[1]
        except TypeError:
            raise BinaryTreeError('empty tree has no left subtree')

    def get_right_subtree(self):
        """
        :return: (BinaryTree) Right Child subtree
        """
        try:
            return self.__content[2]
        except TypeError:
            raise BinaryTreeError('empty tree has no right subtree')

    def __str__(self):
        """
        :return: (str) string representation of that tree
        """
        if self.is_empty():
            return '()'
        else:
            repr_left = str(self.get_left_subtree())
            repr_right = str(self.get_right_subtree())
            return '({:s}, {:s}, {:s})'.format(str(self.get_data()), repr_left, repr_right)

    def size(self):
        """
        :return: (int) numbre of Nodes in Tree
        """
        pass
        
    def height(self):
        """
        :return: (int) height of that tree
        """
        pass

    def is_leaf(self):
        """
        :return: (bool) True iff tree is a leaf
        """
        pass

if __name__ == '__main__':
   import doctest
   doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS, verbose=True)


