// ------------- btree.h

#ifndef BTREE_H
#define BTREE_H

#ifdef ZTC
#include <fstream.hpp>
#else
#include <fstream.h>
#endif
#include "linklist.h"
#include "node.h"

class Key;

// -------- b-tree index file
class Index : public FileHeader	{
public:
	Index(String name) : FileHeader(name) {}
	Bool NewFile() { return newfile; }
};

class TNode;

// -------- b-tree header record
struct TreeHeader {
	NodeNbr rootnode;	// node number of the root
	int keylength;	 	// length of a key in this b-tree
	TreeHeader() { rootnode = keylength = 0; }
};

// --------- b-tree index
class Btree : public LinkedListEntry	{
	TreeHeader header;	// btree header
	NodeNbr currnode;		// current node number
	TNode *trnode;			// -> current node value
	Key *nullkey;			// for padding nodes and calling Make
	Index& index;			// index file this tree lives in
	long headeraddr;		// offset where header lives
public:
	Btree(Index& ndx, Key *ky);
	~Btree();
	void Insert(void *keypointer);
	void Delete(void *keypointer);
	Bool Find(void *keypointer);
	Key *Current();
	Key *First();
	Key *Last();
	Key *Next();
	Key *Previous();
	void SetKeyLength(int kl) { header.keylength = kl; }
	Index& IndexFile()        { return index; }
	Key *NullKey() 			  { return nullkey; }
	NodeNbr Root() 			  { return header.rootnode; }
	NodeNbr KeyLength() 		  { return header.keylength; }
};

// ------------- b-tree TNode class
class TNode : public Node	{
	friend Btree;
	struct TNodeHeader	{
		Bool isleaf;			// true if node is a leaf
		NodeNbr parent;		// parent to this node
		NodeNbr leftsibling;	// left sibling node
		NodeNbr rightsibling;// right sibling node
		int keycount;			// number of keys in this node
		NodeNbr lowernode;	// lower node associated with
									// keys < keys in this node
		TNodeHeader()
			{ isleaf = False; parent = leftsibling =
				rightsibling =	keycount = lowernode = 0; }
	} header;
	Key *currkey;				// current key
	Btree *btree;				// btree that owns this node
	LinkedListHead keys;		// the keys in this node
public:
	TNode(Btree *bt, NodeNbr node);
	~TNode();
	Bool SearchNode(Key *keyvalue);
	void Insert(Key *keyvalue);
	int m();
	void WriteKey(Key *thiskey);
	void Adopt(NodeNbr node);
	void Adoption();
	Bool isLeaf() 			  { return header.isleaf; }
	NodeNbr Parent() 		  { return header.parent; }
	NodeNbr LeftSibling()  { return header.leftsibling; }
	NodeNbr RightSibling() { return header.rightsibling; }
	int KeyCount() 		  { return header.keycount; }
	NodeNbr LowerNode() 	  { return header.lowernode; }
	Bool Redistribute(NodeNbr sib);
	Bool Implode(TNode &right);
	int NodeHeaderSize()
		{ return sizeof(TNodeHeader)+Node::NodeHeaderSize(); }
	TNode& operator=(TNode &tnode);
};

#endif

