#include "SortedBagIterator.h"
#include "SortedBag.h"
#include <exception>

using namespace std;

SortedBagIterator::SortedBagIterator(const SortedBag& b) : bag(b) {
	// Best case: O(1) Worst case: O(n) Average case: O(log n)
	this->first();
}

TComp SortedBagIterator::getCurrent() {
	//O(1)
	if(this->valid())
		return this->current->elem;
	else
		throw exception();
}

bool SortedBagIterator::valid() {
	//O(1)
	if(this->current == nullptr)
		return false;
	return true;
}

void SortedBagIterator::next() {
	// Best case: O(1) Worst case: O(n) Average case: O(log n)
	if(this->valid())
	{
		if(this->currentCount > 1)
			this->currentCount--;
		else
		{
			if(this->current->right != nullptr)
			{
				this->current = this->current->right;
				while(this->current->left != nullptr)
					this->current = this->current->left;
				this->currentCount = this->current->count;
			}
			else
			{
				BSTNode* currentParent = this->current->parent;
				while(currentParent != nullptr && currentParent->right == this->current)
				{
					this->current = currentParent;
					currentParent = currentParent->parent;
				}
				this->current = currentParent;
				if(this->current != nullptr)
					this->currentCount = this->current->count;
				else
					this->currentCount = 0;
			}
		}
	}
	else
		throw exception();
}

void SortedBagIterator::first() {
	// Best case: O(1) Worst case: O(n) Average case: O(log n)
	this->current = this->bag.root;
	if(this->current != nullptr){
		while(this->current->left != nullptr)
			this->current = this->current->left;
		this->currentCount = this->current->count;
	}
	else{
		this->currentCount = 0;
	}
}
