//
//  NAME
//    plist.cpp
//
//  DESCRIPTION
//    This file contains the function definitions for the member
//    functions of the plist class and global functions which are
//    related to the plist class.
//
//    For descriptions of the parameters and return values,
//    see plist.h.
//


//
//  Include files.
//

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

//
//  NAME
//    plist::element
//
//  DESCRIPTION
//    Structure of an element used in the linked list of people.
//
//  MEMBERS
//    data  - person.
//    next  - pointer to the next element in the linked list.
//

struct plist::element {
   person           data;
   plist::element * next;
};

//
//  NAME
//    plist::plist()
//
//  DESCRIPTION
//    This is the default constructor for the plist class.
//

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

//
//  NAME
//    plist::plist(const plist& p)
//
//  DESCRIPTION
//    This is the copy constructor for the plist class.  It
//    uses a local pointer to traverse the source list.
//

plist::plist(const plist& otherList) {
   element * currpos = otherList.head;

   clearList();

   while (currpos != NULL) {
      addToEnd(currpos->data);
      currpos = currpos->next;
      }

   return;
}

//
//  NAME
//    plist::~plist
//
//  DESCRIPTION
//    This is the destructor for the plist class.
//

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


//
//  NAME
//    plist::operator=
//
//  DESCRIPTION
//    This is the assignment operator for the plist class.  It
//    uses a local pointer to traverse the source list.
//

const plist& plist::operator=(const plist& otherList) {
   element * currpos = otherList.head;

   if (this != &otherList) {
      clearList();

      while (currpos != NULL) {
         addToEnd(currpos->data);
         currpos = currpos->next;
         }

      }

   return *this;
}

//
//  NAME
//    plist::addToEnd
//
//  DESCRIPTION
//    This functions adds the given person to the end of the list.
//    It traverses the list from the head to find the end, then adds
//    a new element to the end of the list.
//

void plist::addToEnd(person& p) {
   element * pe = newElement(p);

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

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

//
//  NAME
//    plist::getFirst
//
//  DESCRIPTION
//    This function gets the first person from the list.  The member
//    variable "current" is set to point to the head of the list, and
//    the person information stored in that element is returned, if such
//    an element exists.
//

bool plist::getFirst(person& p) {
   current = head;
   if (current == NULL) {
      return false;
      }
   p = current->data;
   return true;
}

//
//  NAME
//    plist::getNext
//
//  DESCRIPTION
//    This function gets the person information for the next person.
//    The "current" pointer is moved ahead one position in the list,
//    and the person information stored in that element is returned,
//    if such an element exists.
//

bool plist::getNext(person& p) {
   current = current->next;
   if (current == NULL) {
      return false;
      }
   p = current->data;
   return true;
}

//
//  NAME
//    plist::atEnd
//
//  DESCRIPTION
//    This function determines if the list is empty by seeing if the
//    "current" member variable is NULL or not.
//

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

//
//  NAME
//    plist::clearList
//
//  DESCRIPTION
//    This function removes all elements from the list by traversing
//    the list from the head and deallocating each element.  The
//    "current" member variable is used to traverse the list, and the
//    local variable "next" points to the next element.  When the
//    list has been empties, the "head" and "current" member variables
//    are set to NULL.
//

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

//
//  NAME
//    operator<<
//
//  DESCRIPTION
//    This function is the output operator for the plist class.
//
//  PARAMETERS
//    os  (in/out) - output stream.
//    pl  (in)     - plist to output.
//
//  RETURNS
//    reference to the output stream.
//

ostream& operator<<(ostream& os, const plist& pl) {
   person           p;
   int              count = 0;
   plist::element * pe    = pl.head;

   while (pe != NULL) {
      os << pe->data;
      count++;
      pe = pe->next;
      }

   cout << endl;
   cout << "There are " << count << " people in the list." << endl;

   return os;
}

//
//  NAME
//    plist::newElemment
//
//  DESCRIPTION
//    This function allocates a new list element and copies the given
//    person information into it.
//
//  PARAMETESRS
//    p  (in) - person information to copy into the new element.
//
//  RETURNS
//    pointer to the newly allocated list element
//

plist::element * plist::newElement(person& p) const {
   element * pe = new element;
   pe->data = p;
   pe->next = NULL;
   return pe;
}

//
//  NAME
//    plist::moveToEnd
//
//  DESCRIPTION
//    This function causes the "current" member variable to point to
//    the last element in the list.  This function assumes that the
//    list is not empty.
//
//  PARAMETERS
//    (none)
//
//  RETURNS
//    (none)

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

//
//  End of file.
//