#include <iostream>
#include "LinkedList.h"
using namespace std;

LinkedList::~LinkedList() {
  LinkNode* current = head;
  LinkNode* nextLinkNode;
  while (current != NULL) {
    nextLinkNode = current->next;
    delete current;
    current = nextLinkNode;
  }
}

/**
 * Returns the count of the number of elements in the Collection
 */
int LinkedList::size() const {
  LinkNode* current = head;
  int count = 0;
  while (current != NULL) {
    count++;
    current = current->next;
  }
  return count;
}

/**
 * Adds the given integer value to the Collection. Placement index of
 * the newly added element is assumed to be first (index=0).
 */
void LinkedList::add(int pValue) {
  LinkNode* newNode = new LinkNode(pValue);
  
  newNode->next = head;
  head = newNode;
}

/**
 * Returns the integer value of the first element of the Collection.
 */
int LinkedList::first() const {
  return head->data;
}

int LinkedList::get(int index) const {
  if (index < 0) {
    return -1;
  }
  LinkNode* current = head;
  int currentIndex = 0;
  while (current != NULL && currentIndex != index) {
    current = current->next;
    currentIndex++;
  }
  if (currentIndex == index && current != NULL) {
    return current->data;
  }
  else {
    return -1;
  }
}

void LinkedList::add(int data, int index) {
  if (index >= 0) {
    LinkNode* current = head;
    LinkNode* previous = NULL;
    int currentIndex = 0;
    while (current != NULL && currentIndex != index) {
      previous = current;
      current = current->next;
      currentIndex++;
    }
    
    if (currentIndex == index) {
      LinkNode *newNode = new LinkNode(data);
      newNode->next = current;
      if (index == 0) {
        head = newNode;
      }
      else {
        previous->next = newNode;
      }
      
      
    }
  }
}

/**
 * Returns the top element of the stack without removing it
 */
int LinkedList::peek() const {
  return first();
}

/**
 * Removes (and returns) the top element of the stack
 */
int LinkedList::pop() {
  int value = head->data;
  
  LinkNode *next = head->next;
  delete head;
  head = next;
  return value;
}

/**
 * Pushes the given value onto the top of the stack
 */
void LinkedList::push(int value) {
  add(value);
}

LinkNode* reverse(LinkNode *current) {
  if (current->next == NULL) {
    return current;
  }
  else {
    LinkNode* beginning = reverse(current->next);
    current->next->next = current;
    current->next = NULL;
    return beginning;
  }
}

void LinkedList::reverse() {
  head = ::reverse(head);
}
