// Symmetrically linked list implementation
// By: Nick Cash
// Coded for Computer Science III

// Note:
//       C++'s STL has a very good list data type implementation.
//
//       While I would normally use it, the purpose of this assignment
//       is to show the workings and understanding of lists, so I will be
//       avoiding it on purpose, while replicating many of its features.

// Inclusion guard
#ifndef INCLUDE_LIST_LIB
#define INCLUDE_LIST_LIB

template<class T>
class cList
{
  public:
          class Element
          {
             Element *next;
             Element *prev;

             public:
              T data;

              void SetNext(Element* x) { next = x; }
              void SetPrev(Element* x) { prev = x; }

              Element* GetNext() { return next; }
              Element* GetPrev() { return prev; }
          };

          // Constructors and Destructors
          cList();
         ~cList();

          // Information about the list
          unsigned int Size();           // Return the number of elements in the list
          bool Empty();                  // Return true if list is empty
          void Print();                  // Print out each element

          // List manipulation
          void Reverse();                // Reverse the direction of the list
          void Clear();                  // Delete all elements

          // Data insertion and deletion
          void PushFront(const T&);      // Add item to front of the list
          void PushBack(const T&);       // Add item to the back of the list
          void Insert(Element*,Element*);// Insert element before another one
          void PopFront();               // Remove the first element from the list
          void PopBack();                // remove the last element from the list
          void Delete(const T&);         // Delete one element with certain data
          void Erase(const T&);          // Erase all elements with certain data

          // Data retrieval
          Element* GetStart() { return start; } // For list traversal
          Element* GetEnd() { return end; }     // For list traversal

  private:
          void Unlink(Element*);          // Unlink an element from the list
          void Link(Element*, bool);      // Link an element into the list

          Element* start;                 // Keep track of the beginning
          Element* end;                   // Keep track of the end
};

#endif // INCLUDE_LIST_LIB