#ifndef NULL_CLASS_DEFINED
#define NULL_CLASS_DEFINED
class CNullClass {};
#endif

#define TTREENODE(TYPE) TTreeNode<TYPE,CNullClass>

enum ETreeNodeState {
    ETNS_Unknown = -1,
    ETNS_None,
    ETNS_Plus,
    ETNS_Minus,
};

template <class TYPE, class BaseClass>
class TTreeNode : public TDoubleLinkTreeRef<TYPE, BaseClass>
{
public:
    ETreeNodeState m_eTNS;
    CStr m_strName;
    // runtime...
    HTREEITEM m_hTI;
public:
    TTreeNode(const char* pcszName = NULL)
        : m_strName(pcszName)
    {
        m_eTNS = ETNS_Unknown;
        // runtime...
        m_hTI = NULL;
    }
    void SetAsRoot()
    {
        ASSERT(this);
        m_eTNS = ETNS_Unknown;
        // runtime...
        m_hTI = TVI_ROOT;
    }
	TYPE FindNode(HTREEITEM hTI) const
    {
        if (this) {
		    if (m_hTI == hTI)
			    return (TYPE)this;

            TYPE pChild = m_pChild;
            while(pChild) {
                TYPE pFound = pChild->FindNode(hTI);
			    if (pFound)
				    return pFound;
                pChild = pChild->m_pNext;
            }
        }

	    return NULL;
    }
    void Validate(CTreeCtrl& TC)
    {
        if (m_eTNS == ETNS_Unknown) {
            TYPE pChild = m_pChild;

            if (pChild) {
                m_eTNS = ETNS_Plus;
            } else {
                m_eTNS = ETNS_None;
            }
            while(pChild) {
                pChild->Validate(TC);
                pChild = pChild->m_pNext;
            }
        }
    }
	void InsertNode(CTreeCtrl& TC, TYPE pNode, HTREEITEM hTIAfter = TVI_LAST)
    {
        ASSERT(this && &TC);
	    TV_INSERTSTRUCT tvi;

        memset(&tvi, 0, sizeof(tvi));

        tvi.hParent = this ? m_hTI: TVI_ROOT;
	    tvi.hInsertAfter = hTIAfter;

	    tvi.item.mask = TVIF_STATE | TVIF_TEXT;
        tvi.item.stateMask = TVIS_EXPANDED;
        tvi.item.state = (pNode->m_eTNS == ETNS_Minus) ? TVIS_EXPANDED: 0;
	    //tvi.item.iImage = 0;

	    tvi.item.pszText = (char *)(LPCTSTR)pNode->m_strName;

	    pNode->m_hTI = TC.InsertItem(&tvi);
    }
    void InsertRecursive(CTreeCtrl& TC)
    {
        TYPE pNode = m_pChild;

        while(pNode) {
            InsertNode(TC, pNode);
            pNode->InsertRecursive(TC);
            pNode = pNode->m_pNext;
        }
    }
};
