// Copyright (C) 1996 DIMACS Center, Rutgers, The State University of New Jersey
// Author(s): Patricia K. Fasel (Los Alamos Nat. Lab.), Jonathan Berry
// This software is copyrighted by the DIMACS Center at Rutgers, The State
// University of New Jersey.  IT IS PROVIDED AS IS, AND THE AUTHORS, DIMACS, AND
// RUTGERS, THE STATE UNIVERSITY OF NEW JERSEY  DISCLAIM
// ALL LIABILITY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
// DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
// IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
// NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
// MODIFICATIONS.
// The authors hereby grant permission to use, copy, modify, distribute,
// and license this software and its documentation for any purpose, provided
// that existing copyright notices are retained in all copies and that this
// notice is included verbatim in any distributions. No written agreement,
// license, or royalty fee is required for any of the authorized uses.
// Modifications to this software may be copyrighted by their authors
// and need not follow the licensing terms described here, provided that
// the new terms are clearly indicated on the first page of each file where
// they apply.
// Last File Update: 21-Jul-1997
// 
#ifndef List_h
#define List_h
#include <iostream.h>
#include <stddef.h>
#include <LINK/basic/Container.h>
class Vertex;
class Edge;
template <class Item> class SortedList;


template <class Item> class List;
//template <class Item> class CollectionWrapper;
//template <class Item> class ListWrapper;
template <class Item>
class ListNode : public ContainerNode {
public:
    friend class List<Item>;
    friend class SortedList<Item>;
    void*               info() const         	{return (void *) &item; }  
    ListNode*           next() const    	{return nxt;  		}
    ListNode*           setNext(ListNode* y)	{return nxt = y;  	}
protected:
    ListNode(const Item passed_item) : nxt(0), item(passed_item) {}
    Item		getItem() const	{ return item;	    }
    Item		item;
    ListNode*		nxt;
    //********************************************************************
    //** Memory Management ***********************************************
    //********************************************************************
    //ListNode<Item>*	mm_next;
    //static ListNode<Item>*mm_free_store;
    //static const int	mm_block_size;
    //void *operator new(size_t);
    //void operator delete(void *p, size_t);
    //********************************************************************
};
template <class Item>
class List : public SimpleContainer<Item> {
public:
    List();
    List(const List<Item>& c);
    List(const Container<Item>& c);
    virtual ~List();
    Item		info(const ContainerNode *cn) const;
    List<Item>&         operator=(const List<Item>& copy_list);
    //List<Item>&	copy(List<Item>& copy_list) 
    //				{*this = copy_list; return *this; }
    int			size() const;	
    Bool		emptyQ() const	{ return listEnd(_first);	}
    Bool		fullQ() const	{ return FALSE; 		}
    Bool            	sortedQ() const { return FALSE; 		}
    DataType            type() const    { return LIST; 			}
    ContainerNode*      prepend(const Item i);
    ContainerNode*      append(const Item i);
    ContainerNode*      insert(const Item i);
    ContainerNode*      insertBefore(const Item i, ContainerNode * n);
    ContainerNode*      insertAfter(const Item i, ContainerNode * n);
    Item                get();          
 
    Bool		memberQ(const Item& i) const;
    ContainerNode*      search(const Item& item) const;
    void		sort(int (*)(const Item&, const Item&));
    Item		first() const;
    Item		last() const;
    void		remove(const Item i);
    void                clear();
    ContainerNode*      predecessor(const ContainerNode * n) const;
    ContainerNode*      successor(const ContainerNode * n) const;
    int                 rank(Item& item) const;
    ostream&            display(ostream& os) const;
   // List<Item>&       scramble()
#ifdef STK_LISTS
    PRIMITIVE			retrieveHeader();
    PRIMITIVE			unprotectHeader();
#endif
    //friend class ListWrapper<Item>;
    //friend class CollectionWrapper<Item>;
protected:
    ListNode<Item>*		_first; 
    //*********************************************************************
    //** When STk lists and LINK lists were one and the same, we couldn't
    //** use the _last pointer.  However, that is no longer the case, so
    //** it is back.  The listEnd(...) method is there to provide flexibility
    //** to switch back and forth between representations.
    //*********************************************************************
    ListNode<Item>*		_last; 
    int 			listEnd(const ListNode<Item>* n) const
					{ return (n==0); }
    //*********************************************************************
    ListNode<Item>*		cn2ListNode(const ContainerNode *n) const;
    ListNode<Item>*		firstNode() const;
    ContainerNode*		ListNode2cn(ListNode<Item> *n) const;
    int                 	iterate(Iterator<Item>& iter, Item& item) const;
#ifdef STK_LISTS
    void			createProtectedHeader();
#endif
};
//#ifdef DEFINE_List_TEMPLATE
#include <LINK/basic/List.cpp>
//#endif
#endif
