#include "avl.h"


// This method searches a Node in the AVL tree.
// Parameters: The information to be searched.
// Return value: A pointer to the node, if found. NULL pointer otherwise.
NodePtr AVLTree::Find(const BasicInfo& toFind) const
{
	if(root == NULL) return NULL;
	return root->Find(toFind);
}


// This method inserts a new node into the tree.
// Parameters: The information to insert.
// Return value: a pointer to the newlly inserted node, or NULL if the Node 
// already exists or the insertion failed.
NodePtr AVLTree::Insert(BasicInfo& toInsert)
{
	if(root == NULL){
		if((root = new Node(&toInsert)) == NULL) return NULL;
		return root;
	}
	return root->Insert(toInsert, root);
}


// This methos removes a certain node from the tree.
// Parameters: The information to be removed.
// Return value: None - The tree's Find function should be called first and 
// only if succeeds, Remove should be called.
void AVLTree::Remove(const BasicInfo& toRemove)
{
	NodePtr extract = Find(toRemove);
	NodePtr replacer = extract->getReplacer();
	if(replacer == NULL){ //the soon to be gone node is a leaf
		NodePtr dad = extract->getDaddy();
		extract->removeLeaf(root);
		delete extract;
		if(root) checkTree(dad);
	}else{
		NodePtr startCheck = replacer->Replace(extract, root);
		checkTree(startCheck);
	}
	return;
}


// this function removes a node from a salay tree. It locates it by address
// because there can be several nodes with the same key in this tree. 
void AVLTree::RemoveByAdr(NodePtr toRemove)
{
	NodePtr replacer = toRemove->getReplacer();
	if(replacer == NULL){ //the soon to be gone node is a leaf
		NodePtr dad = toRemove->getDaddy();
		toRemove->removeLeaf(root);
		delete toRemove;
		if(root) checkTree(dad);
	}else{
		NodePtr startCheck = replacer->Replace(toRemove, root);
		checkTree(startCheck);
	}
	return;
}


float AVLTree::getMaxSal()
{
	NodePtr curr = root->goRight();
	SalaryInfo *max = static_cast<SalaryInfo*>(curr->getData());
	return max->getSal();
}



ostream& AVLTree::print(ostream& out) const
{ 
	if(root == NULL) return out;
	return root->print(out);
}


ostream& operator<<(ostream& out, const AVLTree& toPrint)
{
	return toPrint.print(out);
}
