/* list.cpp
 *
 * Routines for a doubly-linked circular list with a sentinel
 */


#include "list.H"
#include "person.H"

class Person;


// Private functions

void List::add_to_head( Lnode  *n )  // ADD NODE TO HEAD OF LIST
{
    // n->next should be NULL

    sentinel->next->prev = n;
    n->next = sentinel->next;
    sentinel->next = n;
    n->prev = sentinel;
}


void
List::add_to_tail( Lnode  *n )  // ADD NODE TO TAIL OF LIST
{
    // n->next should be NULL

    sentinel->prev->next = n;
    n->prev = sentinel->prev;
    sentinel->prev = n;
    n->next = sentinel;
}


void
List::remove( Lnode  *n )  // REMOVE NODE FROM LIST, BUT DO NOT DELETE IT
{
    n->next->prev = n->prev;
    n->prev->next = n->next;
    
    n->next = NULL;  // do this to catch dangling references later
}

void
List::remove_all()  // DELETE ALL NODES ON THE LIST
{
    Lnode *e;
    while (!empty()) {
	e = get_next(NULL);
	remove(e);
	delete e;
    }
}


// Public Functions

int
List::empty()  // RETURN 1 IF LIST IS EMPTY, 0 OTHERWISE
{
    return sentinel->next == sentinel;
}


/*Lnode *
List::head()  // RETURN HEAD NODE OF LIST
{
    if (empty())
	return NULL;
    else
	return sentinel->next;
}
*/
Lnode *
List::get_next( Lnode  *n )  // RETURN NEXT NODE IN LIST
{
    if( n == NULL)
	if( empty())
	    return NULL;
	else
	    return sentinel->next;
    else if (n->next == sentinel)
	return NULL;
    else
	return n->next;
}

void
List::print()  // PRINT THIS LIST 
{
    Lnode  *n;
    cout << "List:\n";

    for (n=sentinel->next; n != sentinel; n=n->next) {
	n->data->print();
	cout << "  ";
    }

    cout << "\n";
}

void
List::add_data( Person *data )
{
    add_to_tail( new Lnode ( data ) );
}

void
List::remove_data( Person *data )
{
    Lnode * n;

    for (n = sentinel->next; n != sentinel; n=n->next)
	if (n->data == data) {
	    remove( n );
	    return;
	}
    
    cerr << "remove_data: Couldn't find data to remove: ";
    data->print();
    cerr << "\n"; 
}

List::List()
{
    sentinel = new Lnode();
    sentinel->next = sentinel->prev = sentinel;
}
    
