#pragma once

#include <memory>

template<typename T>
class RawNode
{
public:
    RawNode(T data)
        : mData(data)
    {


    }

    ~RawNode()
    {
        if(mLeftChild)
        {
            delete mLeftChild;
        }

        if(mRightChild)
        {
            delete mRightChild;
        }
    }

    void addChild(RawNode* child)
    {
        if(!mLeftChild)
        {
            mLeftChild = child;
        }
        else
        {
            mRightChild = child;
        }
    }

    bool isLeaf() const
    {
        return !mLeftChild && !mRightChild;
    }

    T getData() const
    {
        return mData;
    }

    RawNode* getLeftChild() const
    {
        return mLeftChild;
    }

    RawNode* getRightChild() const
    {
        return mRightChild;
    }

private:
    T mData;
    unsigned char mTag{0};
    RawNode* mLeftChild{nullptr};
    RawNode* mRightChild{nullptr};
};

template<typename T>
class RawTree
{
public:
    RawTree()
    {

    }

    ~RawTree()
    {
        if (mRootNode)
        {
            delete mRootNode;
        }
    }

    void addRootNode(RawNode<T>* root)
    {
        mRootNode = root;
    }

    RawNode<T>* getRootNode() const
    {
        return mRootNode;
    }

private:
    RawNode<T>* mRootNode{nullptr};
};
