#pragma once
#include "Node.h";

template< class T >
class List
{
	public:
		
		List(void)
		{
			this->root = NULL;
			this->count = 0;
		}

		~List(void)
		{
			Node<T> *walker = root;
			for ( int i = 0; i < this->count; i++ )
			{
				Node<T> *temp = walker->next;
				walker = walker->next;

				delete temp;
			}
		}

		
		void addroot(const T& item)
		{
			Node<T> *temp = new Node<T>(item);
			if ( root == NULL )
				root = temp;
			else
			{
				temp->next = root;
				root = temp;
			}
				

			this->count += 1;
		}

		void addElementAt(int index, const T& item)
		{
			if ( index == 0 ) {
				addroot(item);
			}
			else {
				Node<T> *temp = new Node<T>(item);
				Node<T> *walker = root;
				if ( index >= count ) {
					while ( walker->next != NULL )
						walker = walker->next;
					walker->next = temp;
				}
				else {
					for(int i = 0; i < ( index - 1 ); i++)
						walker = walker->next;
					temp->next = walker->next;
					walker->next = temp;
				}
				
				this->count += 1;
			}
		}

		bool deleteElementAt(int index)
		{
			if ( index > this->count )
				return false;
			else if (index == 0)
			{
				Node<T> *temp = this->root->next;
				root = temp;
			}
			else
			{
				Node<T> *walker = this->root;
				for ( int i = 0; i < (index-1); i ++ )
				{
					walker = walker->next;
				}
				
				Node<T> *temp = walker->next;
				walker->next = walker->next->next;

				delete temp;
			}
			
			this->count--;

			return true;
		}

		bool deleteElement(const T& item)
		{
			if ( root == NULL )
				return false;
			else if ( root->data == item )
			{
				Node<T> *temp = root;
				root = temp->next;

				delete temp;
	
				this->count--;
				
				return true;
			}
			else
			{
				Node<T> *walker = this->root;
				while(walker->next->data != item && walker->next->next != NULL)
					walker = walker->next;
				Node<T> *temp = walker->next;
				walker->next = temp->next;
				delete temp;

				this->count--;

				return true;
			}
			return false;
		}

		bool isEmpty() const
		{
			if ( this->count > 0 )
				return false;

			return true;
		}

		bool set(int index, const T& item)
		{
			if ( index > this->count )
				return false;

			else
			{
				Node<T> *walker = this->root;

				for ( int i = 0; i < index; i ++ )
				{
					walker = walker->next;
				}
				walker->data = item;
			}

			return true;
		}

		T get(int index) const
		{
			if ( index > this->count )
				return NULL;
			else
			{
				Node<T> *walker = root;
				for (int i = 0; i < index; i++)
					walker = walker->next;

				return walker->data;
			}
			return NULL;
		}

		int size()
		{
			return this->count;
		}

	private:
		Node<T>* root;
		int count;
};

