#include "LinkedList.h"

LinkedList::LinkedList() { 
  head = tail = NULL;
  size = 0;
  //makeEmpty();
}

void LinkedList::makeEmpty() {
	if(head != NULL) deleteList(head);
	head = tail = NULL;
	size = 0;
}

void LinkedList::insert(int val) {
	if (size == 0) {
		head = new Node();
		if(head == NULL) {
		  std::cerr<<"Error allocating new nodes.\n";
		  ofstream status("status.txt");
		  status << "Exiting\n";
		  status.close();
		  MPI_Finalize();
		  exit(1);
		}
		(*head).value = val;
		(*head).next = NULL;
		tail = head; 
		size++;
		return;
	}
	Node* temp = new Node();;
	if(temp == NULL) {
	  std::cerr<<"Error allocating new nodes.\n";
	  ofstream status("status.txt");
	  status << "Exiting\n";
	  status.close();
	  MPI_Finalize();
	  exit(1);
	}
	(*temp).next = NULL;
	(*temp).value = val;
	(*tail).next = temp;
	tail = temp;
	temp = NULL;
	delete temp;
	size++;
}

int LinkedList::length() {
	return size;
}

int LinkedList::get(int m){
	if (m > size) throw IndexOutofBoundsException();
	return get_r(m, *head);
}

int LinkedList::get_r(int m, Node node){
    if(m == 0) return node.value;
	return get_r(m-1, *node.next);
}

int LinkedList::find(int n) {
	return find_r(n, *head, 0);
}

int LinkedList::find_r(int n, Node node, int index) {
	if(node.value == n) return index;
	if(node.next == NULL) return -1;
	return find_r(n, *node.next, index+1);
}

int* LinkedList::toArray() {
	array = new int[size];
	if(array == NULL) {
		std::cout<<"Error allocating array for list\n";
		ofstream status("status.txt");
		status << "Exiting\n";
		status.close();
		MPI_Finalize();
		exit(1);
		return array;
	}
	if(size==0) return array;
	Node node = *head;
	for(int i = 0; i < size; i++) {
		array[i] = node.value;
		if(node.next != NULL)
			node = *node.next;
	}
	return array;
}

void LinkedList::destroyArray() {
	delete[] array;
}

void LinkedList::deleteList(Node* n) {
	Node* next;
	while(n != NULL) {
	  next = (*n).next;
	  delete n;
	  n = next;
	}
}