#ifndef _CEGOBTREEMANAGER_H_INCLUDED_
#define _CEGOBTREEMANAGER_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoBTreeManager.h
// ------------------
// Cego BTree+ manager class definition
//                                                         
// Design and Implementation by Bjoern Lemke               
//     
// (C)opyright 2000-2025 Bjoern Lemke
//
// INTERFACE MODULE
//
// Class: CegoBTreeManager
// 
// Description: This class implements the btree algorithm to be used for table index objects.
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

// LFC INCLUDES
#include <lfcbase/Chain.h>
#include <lfcbase/ListT.h>
#include <lfcbase/AVLTreeT.h>

// CEGO INCLUDES
#include "CegoDefs.h"
#include "CegoDataType.h"
#include "CegoField.h"
#include "CegoDataPointer.h"
#include "CegoObjectManager.h"
#include "CegoBTreeNode.h"
#include "CegoBTreeValue.h"
#include "CegoAdminHandler.h"

class CegoBTreeManager {

public:
    
    CegoBTreeManager(CegoObjectManager* pObjMng, CegoBTreeObject *pBTO);
    ~CegoBTreeManager();

    void createCache();

    void commit(CegoDataPointer& sysEntry);
    void rollback();
    
    void insertBTreeWithCommit(const CegoDataPointer& dp,
		     const CegoBTreeValue &iv,
		     unsigned long long tid);
    
    void deleteBTree(const CegoBTreeValue &iv,
		     const CegoDataPointer& dp,
		     unsigned long long tid);

    void insertBTree(const CegoDataPointer& dp, 
		      const CegoBTreeValue &iv,
		      unsigned long long tid);

    void deleteBTree(const CegoDataPointer& sysEntry, 
		     const CegoBTreeValue &iv,
		     const CegoDataPointer& dp,
		     unsigned long long tid);

    bool verifyBTree(CegoAdminHandler* pAH);

    void dumpBTree(Chain& chainDump);

    unsigned getNumPages();
    unsigned freeBTree();

    unsigned traceBTree();
	
private:

    class BTreeCache {
	
    public:
	
	BTreeCache();
	~BTreeCache();

	CegoBufferPage* newCachePage(CegoBufferPage& bp, const CegoBufferPage::PageType pageType, bool copyPage);
	CegoBufferPage* getCachePage(PageIdType pageId);

	CegoBufferPage* getFirst();
	CegoBufferPage* getNext();
	
    private:

	class CacheEntry {

	public:

	    CacheEntry()
	    {
	    }

	    CacheEntry(PageIdType pageId)
	    {
		_pageId = pageId;
	    }
	    
	    CacheEntry(CegoBufferPage* pBP)
	    {
		_pBP = pBP;
		_pageId = pBP->getPageId();
	    }
	    	    
	    ~CacheEntry()
	    {
	    }

	    CegoBufferPage* getPage() const
	    {
		return _pBP;
	    }
	    
	    void setPage(CegoBufferPage* pBP)
	    {
		_pBP = pBP;
		_pageId = pBP->getPageId();
	    }
	    
	    CacheEntry& operator = ( const CacheEntry& e)
	    {
		_pBP = e._pBP;
		_pageId = e._pageId;
		return (*this);
	    }

	    bool operator == ( const CacheEntry& e)
	    {
		if ( _pageId == e._pageId )
		    return true;
		return false;
	    }

	    bool operator < ( const CacheEntry& e)
	    {
		if ( _pageId < e._pageId )
		    return true;		
		return false;
	    }

	    bool operator > ( const CacheEntry& e)
	    {
		if ( _pageId > e._pageId )
		    return true;
		return false;
	    }
	    
	    friend ostream& operator << (ostream& s, const CacheEntry& e)
	    {
		s << "(" << e._pageId << ")";
		return s;
	    }
	    
	private:

	    PageIdType _pageId;
	    CegoBufferPage* _pBP;	    
	};

	AVLTreeT<CacheEntry> _cache;
    };

    bool checkDuplicate(const CegoBTreeValue &iv, const CegoBTreeNode &leaf, unsigned long long tid);
    			
    CegoBufferPage* allocPage(CegoBufferPage::PageType type);
    CegoBufferPage* getPage(PageIdType pageId);
    void putPage(CegoBufferPage* pBP);
    
    bool verifyNode(PageIdType pageId, CegoAdminHandler* pAH);
    void dumpNode(Chain& chainDump, unsigned level, PageIdType pageId);
    
    unsigned countNodePages(PageIdType pageId, PageIdType& firstLeafPageId, bool& isFirst);
    unsigned countLeafPages(PageIdType firstLeafPageId);
    
    unsigned freeNodePages(PageIdType pageId, PageIdType& firstLeafPageId, bool& isFirst);
    unsigned freeLeafPages(PageIdType firstLeafPageId);

    unsigned traceNodePages(PageIdType pageId, PageIdType& firstLeafPageId, bool& isFirst);
    unsigned traceLeafPages(PageIdType firstLeafPageId);

    CegoBTreeObject* _pBTO;
    CegoObjectManager* _pObjMng;
    CegoDatabaseManager* _pDBMng;
    
    CegoObject::ObjectType _btreeType;
    ListT<CegoField> _btreeSchema;
    Chain _btreeName;
    unsigned _keyLen;
    unsigned _tabSetId;

    BTreeCache* _pCache;

    unsigned long _verifyCount;
    
    unsigned long _modId;
};
#endif
