#include <stdlib.h>

#include "bool.h"
#include "person.h"
#include "plist.h"


struct plistElem {
   person    * data;
   plistElem * next;
};


plist::plist() {
   head    = NULL;
   current = NULL;
}


plist::plist(const plist& otherList) {
   plistElem * otherCurrPos = otherList.head;
   plistElem * currPos      = NULL;

   //  Clear the list.
   clearList();

   //  Copy the data from the other list.
   while (otherCurrPos != NULL) {
      addToEnd(otherCurrPos->data);
      otherCurrPos = otherCurrPos->next;
      }

   //  Set the current pointer to match that of the other list.
   currPos      = head;
   otherCurrPos = otherList.head;
   while (otherCurrPos != otherList.current) {
      currPos      = currPos->next;
      otherCurrPos = otherCurrPos->next;
      }

   return;
}


plist::~plist() {
   clearList();
}


const plist& plist::operator=(const plist& otherList) {
   plistElem * currPos      = NULL;
   plistElem * otherCurrPos = otherList.head;

   if (this != &otherList) {

      //  Clear the list.
      clearList();

      //  Copy the data from the other list.
      while (otherCurrPos != NULL) {
         addToEnd(otherCurrPos->data);
         otherCurrPos = otherCurrPos->next;
         }

      //  Set the current pointer to match that of the other list.
      currPos      = head;
      otherCurrPos = otherList.head;
      while (otherCurrPos != otherList.current) {
         currPos      = currPos->next;
         otherCurrPos = otherCurrPos->next;
         }

      }

   return *this;
}


void plist::addToEnd(person * p) {
   plistElem * pe = newElem(p);

   if (head == NULL) {
      head = pe;
      current = head;
      return;
      }

   moveToEnd();
   current->next = pe;
   current = pe;
   return;
}


person * plist::getFirst() {
   current = head;
   if (current == NULL) {
      return NULL;
      }
   return current->data;
}


person * plist::getNext() {
   current = current->next;
   if (current == NULL) {
      return NULL;
      }
   return current->data;
}


bool plist::atEnd() const {
   return (current == NULL) ? true : false;
}


void plist::clearList() {
   plistElem * next = NULL;
   current = head;
   while (current != NULL) {
      next = current->next;
      delete current->data;
      delete current;
      current = next;
      }
   head    = NULL;
   current = head;
   return;
}


plistElem * plist::newElem(person * p) {
   plistElem * pe = new plistElem;
   pe->data = p->clone();
   pe->next = NULL;
   return pe;
}


void plist::moveToEnd() {
   if (current == NULL) {
      current = head;
      }
   while (current->next != NULL) {
      current = current->next;
      }
   return;
}