//-----------------------------------------------------------------------------
#include "linkedlistclass.h"
#include <assert.h>
//-----------------------------------------------------------------------------
//----Public parts of linkedlistnode
//-----------------------------------------------------------------------------
//----Initial value constructor
template <class NodeType>
linkedlistnode<NodeType>::linkedlistnode(const NodeType& NewNodeData) {

Data = NewNodeData;
NextNodePointer = NULL;
PreviousNodePointer = NULL;
}
//-----------------------------------------------------------------------------
//----Set and get node data
template <class NodeType>
void linkedlistnode<NodeType>::SetNodeData(const NodeType& NewNodeData) {

Data = NewNodeData;
}
//-----------------------------------------------------------------------------
template <class NodeType>
NodeType linkedlistnode<NodeType>::GetNodeData(void) const {

return(Data);
}
//-----------------------------------------------------------------------------
//----Public parts of linkedlist
//-----------------------------------------------------------------------------
//----Default constructor 
template <class NodeType>
linkedlist<NodeType>::linkedlist(void) {

FirstNodePointer = LastNodePointer = NULL;
}
//-----------------------------------------------------------------------------
//----Copy constructor
template <class NodeType>
linkedlist<NodeType>::linkedlist(const linkedlist<NodeType>& CopyThisList) {

linkedlistnode<NodeType> *CurrentNodePointer;

//----Start list as empty
FirstNodePointer = LastNodePointer = NULL;

//----Look through values in copy list, adding a node for each
CurrentNodePointer = CopyThisList.FirstNodePointer;
while (CurrentNodePointer != NULL) {
    AddAtEnd((*CurrentNodePointer).GetNodeData());
    CurrentNodePointer = CurrentNodePointer->NextNodePointer;
    }
}
//-----------------------------------------------------------------------------
//----Destructor
template <class NodeType>
linkedlist<NodeType>::~linkedlist(void) {

//----Move down to end of list deleting as we go
while (!Empty()) 
    DeleteOldNode(FirstNodePointer);
}
//-----------------------------------------------------------------------------
//----Test if empty
template <class NodeType>
boolean linkedlist<NodeType>::Empty(void) const {

return(FirstNodePointer == NULL);
}
//-----------------------------------------------------------------------------
//----Get data from first node
template <class NodeType>
NodeType linkedlist<NodeType>::GetFirstNodeData(void) const {

//----User is responsible for use, so die if they're stupid
assert(!Empty());

return((*FirstNodePointer).GetNodeData());
}
//-----------------------------------------------------------------------------
//----Get data from last node
template <class NodeType>
NodeType linkedlist<NodeType>::GetLastNodeData(void) const {

//----User is responsible for use, so die if they're stupid
assert(!Empty());

return((*LastNodePointer).GetNodeData());
}
//-----------------------------------------------------------------------------
//----Add node at start
template <class NodeType>
void linkedlist<NodeType>::AddAtStart(const NodeType& NewNodeData) {

linkedlistnode<NodeType> *NewNodePointer;

//----Make a new node with the data
NewNodePointer = MakeNewNode(NewNodeData);

//----If the only node, then also the last node
if (Empty())
    FirstNodePointer = LastNodePointer = NewNodePointer;
else {
    FirstNodePointer->PreviousNodePointer = NewNodePointer;
    NewNodePointer->NextNodePointer = FirstNodePointer;
    FirstNodePointer = NewNodePointer;
    }
}
//-----------------------------------------------------------------------------
//----Add node at end
template <class NodeType>
void linkedlist<NodeType>::AddAtEnd(const NodeType& NewNodeData) {

linkedlistnode<NodeType> *NewNodePointer;

//----Make a new node with the data
NewNodePointer = MakeNewNode(NewNodeData);

//----If empty then link as first and last
if (Empty()) {
    FirstNodePointer = LastNodePointer = NewNodePointer;
    }
//----Otherwise add as last with link
else {
    LastNodePointer->NextNodePointer = NewNodePointer;
    NewNodePointer->PreviousNodePointer = LastNodePointer;
    LastNodePointer = NewNodePointer;
    }
}
//-----------------------------------------------------------------------------
//----Delete from the start of the list if possible
template <class NodeType>
void linkedlist<NodeType>::DeleteAtStart(void) {

//----User is responsible for use, so die if they're stupid
assert(!Empty());

DeleteOldNode(FirstNodePointer);
}
//-----------------------------------------------------------------------------
//----Delete from the end of the list if possible
template <class NodeType>
void linkedlist<NodeType>::DeleteAtEnd(void) {

//----User is responsible for use, so die if they're stupid
assert(!Empty());

DeleteOldNode(LastNodePointer);
}
//-----------------------------------------------------------------------------
//----Dump for debugging
template <class NodeType>
void linkedlist<NodeType>::Dump(void) const {

linkedlistnode<NodeType> *CurrentNodePointer;

cout << endl << "Forwards: ";
CurrentNodePointer = FirstNodePointer;
while (CurrentNodePointer != NULL) {
    cout << CurrentNodePointer->Data << " ";
    CurrentNodePointer = CurrentNodePointer->NextNodePointer;
    }
cout << "Backwards: ";
CurrentNodePointer = LastNodePointer;
while (CurrentNodePointer != NULL) {
    cout << CurrentNodePointer->Data << " ";
    CurrentNodePointer = CurrentNodePointer->PreviousNodePointer;
    }
cout << endl;
}
//-----------------------------------------------------------------------------
//----Private parts of linkedlist
//-----------------------------------------------------------------------------
//----Function to make new nodes and check
template <class NodeType>
linkedlistnode<NodeType> *linkedlist<NodeType>::MakeNewNode(
const NodeType& NewNodeData) const {

linkedlistnode<NodeType> *NewNodePointer;

//----Claim memory (calling node constructor) and check for success
NewNodePointer = new linkedlistnode<NodeType>(NewNodeData);
assert(NewNodePointer != NULL);

return(NewNodePointer);
}
//-----------------------------------------------------------------------------
//----Function to delete a node and update the links
template <class NodeType>
void linkedlist<NodeType>::DeleteOldNode(
linkedlistnode<NodeType> *OldNodePointer) {

//----Internal check for stupidity
assert(OldNodePointer != NULL);

//----Find where it is on the list
if (OldNodePointer == FirstNodePointer)
    if  (OldNodePointer == LastNodePointer)
//----It's the only node
        FirstNodePointer = LastNodePointer = NULL;
    else {
//----It's the first node and not last node
        FirstNodePointer = FirstNodePointer->NextNodePointer;
        FirstNodePointer->PreviousNodePointer = NULL;
        }
else if  (OldNodePointer == LastNodePointer) {
//----It's the last node and not first node
        LastNodePointer = LastNodePointer->PreviousNodePointer;
        LastNodePointer->NextNodePointer = NULL;
        }
    else {
//----It's in the middle somewhere
        OldNodePointer->PreviousNodePointer->NextNodePointer =
OldNodePointer->NextNodePointer;
        OldNodePointer->NextNodePointer->PreviousNodePointer =
OldNodePointer->PreviousNodePointer;
        }

//----Free memory
delete OldNodePointer;
}
//-----------------------------------------------------------------------------
//----Public parts of linkedlistiterator
//-----------------------------------------------------------------------------
//----Constructor taking name of list
template <class NodeType>
linkedlistiterator<NodeType>::linkedlistiterator(
linkedlist<NodeType>& ListToIterate) {

TheList = &ListToIterate;
CurrentNodePointer = NULL;
}
//-----------------------------------------------------------------------------
//----Checks if current and next are there
template <class NodeType>
boolean linkedlistiterator<NodeType>::NodeExists(void) const {

return(CurrentNodePointer != NULL);
}
//-----------------------------------------------------------------------------
template <class NodeType>
boolean linkedlistiterator<NodeType>::NextNodeExists(void) const {

//----User is responsible for use, so die if they're stupid
assert(NodeExists());

return(CurrentNodePointer->NextNodePointer != NULL);
}
//-----------------------------------------------------------------------------
template <class NodeType>
boolean linkedlistiterator<NodeType>::PreviousNodeExists(void) const {

//----User is responsible for use, so die if they're stupid
assert(NodeExists());

return(CurrentNodePointer->PreviousNodePointer != NULL);
}
//-----------------------------------------------------------------------------
//----To the start of the linked list
template <class NodeType>
void linkedlistiterator<NodeType>::ToStart(void) {

CurrentNodePointer = TheList->FirstNodePointer;
}
//-----------------------------------------------------------------------------
//----To the end of the linked list
template <class NodeType>
void linkedlistiterator<NodeType>::ToEnd(void) {

CurrentNodePointer = TheList->LastNodePointer;
}
//-----------------------------------------------------------------------------
//----To the next node of the linked list
template <class NodeType>
void linkedlistiterator<NodeType>::operator ++(void) {

//----User is responsible for use, so die if they're stupid
assert(NodeExists());
if (NextNodeExists())
    CurrentNodePointer = CurrentNodePointer->NextNodePointer;
else CurrentNodePointer = NULL;
}
//-----------------------------------------------------------------------------
//----To the previous node of the linked list
template <class NodeType>
void linkedlistiterator<NodeType>::operator --(void) {

//----User is responsible for use, so die if they're stupid
assert(NodeExists());
if (PreviousNodeExists())
    CurrentNodePointer = CurrentNodePointer->PreviousNodePointer;
else CurrentNodePointer = NULL;
}
//-----------------------------------------------------------------------------
//----Set data of current
template <class NodeType>
void linkedlistiterator<NodeType>::SetCurrentData(const NodeType& NewNodeData) {

//----User is responsible for use, so die if they're stupid
assert(NodeExists());

(*CurrentNodePointer).SetNodeData(NewNodeData);
}
//-----------------------------------------------------------------------------
//----Return current node's data
template <class NodeType>
NodeType linkedlistiterator<NodeType>::CurrentData(void) const {

//----User is responsible for use, so die if they're stupid
assert(NodeExists());

return((*CurrentNodePointer).GetNodeData());
}
//-----------------------------------------------------------------------------
//----Add node before current
template <class NodeType>
void linkedlistiterator<NodeType>::AddBefore(const NodeType& NewNodeData) 
const {

linkedlistnode<NodeType> *NewNodePointer;

//----User is responsible for use, so die if they're stupid
assert(NodeExists());

//----If nothing before, then it's at start
if (!PreviousNodeExists())
    (*TheList).AddAtStart(NewNodeData);
//----Else make node and link in
else {
//----Make a new node with the data
    NewNodePointer = (*TheList).MakeNewNode(NewNodeData);
    NewNodePointer->NextNodePointer = CurrentNodePointer;
    NewNodePointer->PreviousNodePointer = 
CurrentNodePointer->PreviousNodePointer;
    NewNodePointer->PreviousNodePointer->NextNodePointer = NewNodePointer;
    CurrentNodePointer->PreviousNodePointer = NewNodePointer;
    }
}
//-----------------------------------------------------------------------------
//----Add node after current
template <class NodeType>
void linkedlistiterator<NodeType>::AddAfter(const NodeType& NewNodeData) const {

linkedlistnode<NodeType> *NewNodePointer;

//----User is responsible for use, so die if they're stupid
assert(NodeExists());

//----If nothing before, then it's at start
if (!NextNodeExists())
    (*TheList).AddAtEnd(NewNodeData);
//----Else make node and link in
else {
//----Make a new node with the data
    NewNodePointer = (*TheList).MakeNewNode(NewNodeData);
    NewNodePointer->NextNodePointer = CurrentNodePointer->NextNodePointer;
    NewNodePointer->PreviousNodePointer = CurrentNodePointer;
    NewNodePointer->NextNodePointer->PreviousNodePointer = NewNodePointer;
    CurrentNodePointer->NextNodePointer = NewNodePointer;
    }
}
//-----------------------------------------------------------------------------
//----To delete here
template <class NodeType>
void linkedlistiterator<NodeType>::DeleteCurrent(void) {

//----User is responsible for use, so die if they're stupid
assert(NodeExists());

(*TheList).DeleteOldNode(CurrentNodePointer);
CurrentNodePointer = NULL;
}
//-----------------------------------------------------------------------------
//----To delete next
template <class NodeType>
void linkedlistiterator<NodeType>::DeleteNext(void) {

//----User is responsible for use, so die if they're stupid
assert(NextNodeExists());

(*TheList).DeleteOldNode(CurrentNodePointer->NextNodePointer);
}
//-----------------------------------------------------------------------------
//----To delete previous
template <class NodeType>
void linkedlistiterator<NodeType>::DeletePrevious(void) {

//----User is responsible for use, so die if they're stupid
assert(PreviousNodeExists());

(*TheList).DeleteOldNode(CurrentNodePointer->PreviousNodePointer);
}
//-----------------------------------------------------------------------------
