#include "SMIterator.h"
#include "SortedMap.h"
#include <exception>
#include <algorithm>
using namespace std;

SortedMap::SortedMap(Relation r) {
	//Complexity: O(1)
	this->relation = r;
	this->head = nullptr;
	this->length = 0;
}

TValue SortedMap::add(TKey k, TValue v) {
	//Complexity: O(n) - average/worst  O(1) - best
	if (this->head == nullptr){
		this->head = new Node(pair<TKey, TValue>(k, v));
		this->length++;
		return NULL_TVALUE;
	}
	if (this->head->element.first == k){
		TValue value = this->head->element.second;
		this->head->element.second = v;
		return value;
	}
	if(this->relation(k, this->head->element.first)){
		Node* new_node = new Node(pair<TKey, TValue>(k, v));
		new_node->next = this->head;
		this->head = new_node;
		this->length++;
		return NULL_TVALUE;
	}
	Node* previous_node = this->head;
	Node* current_node = this->head->next;
	for(int i = 0; i < this->length-1; i++){
		if (current_node->element.first == k){
			TValue value = current_node->element.second;
			current_node->element.second = v;
			return value;
		}
		if (this->relation(k, current_node->element.first)){
			Node* new_node = new Node(pair<TKey, TValue>(k, v));
			new_node->next = current_node;
			previous_node->next = new_node;
			this->length++;
			return NULL_TVALUE;
		}
		previous_node = current_node;
		current_node = current_node->next;
	}
	previous_node->next = new Node(pair<TKey, TValue>(k, v));
	this->length++;
	return NULL_TVALUE;

}

TValue SortedMap::search(TKey k) const {
	//Complexity: O(n) - average/worst  O(1) - best
	Node* current_node = this->head;
	for(int i = 0; i< this->length; i++){
		if (current_node->element.first == k)
			return current_node->element.second;
		current_node = current_node->next;
	}
	return NULL_TVALUE;
}

TValue SortedMap::remove(TKey k) {
	//Complexity: O(n) - average/worst  O(1) - best
	if(this->head!=nullptr && this->head->element.first == k){
		Node* new_head = this->head->next;
		TValue value = this->head->element.second;
		delete this->head;
		this->head = new_head;
		this->length--;
		return value;
	}
	Node* current_node = this->head;
	for(int i = 1; i< this->length; i++){
		if (current_node->next->element.first == k){
			Node* removed_node = current_node->next;
			TValue value = removed_node->element.second;
			current_node->next = current_node->next->next;
			delete removed_node;
			this->length--;
			return value;
		}
		current_node = current_node->next;
	}
	return NULL_TVALUE;
}

int SortedMap::size() const {
	//Complexity: O(1)
	return this->length;
}

bool SortedMap::isEmpty() const {
	//Complexity: O(1)
	if (this->length == 0)
		return true;
	return false;
}

SMIterator SortedMap::iterator() const {
	//Complexity: O(1)
	return SMIterator(*this);
}

SortedMap::~SortedMap() {
	//Complexity: O(n)
	Node* current_node = this->head;
	for(int i = 0; i < this->length; i++){
		Node* next_node = current_node->next;
		delete current_node;
		current_node = next_node;
	}
}

std::vector<TValue> SortedMap::valueBag() {
	//Complexity: O(n*m) - average/worst  O(n) - best
	vector<TValue> values;
	Node* current_node = this->head;
	for(int i = 0; i < this->length; i++){
		if (find(values.begin(), values.end(), current_node->element.second) == values.end())
			values.push_back(current_node->element.second);
		current_node = current_node->next;
	}
	return values;
}