#ifndef CLASSES_LISTS_HPP
#define CLASSES_LISTS_HPP

/*
**
** lists.hpp
**
** (c) 1999 Didier Levet
**
** Lists/Nodes
**
**
*/


#ifndef  CLIB_EXEC_PROTOS_H
#include <clib/exec_protos.h>
#endif

#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef  EXEC_NODES_H
#include <exec/nodes.h>
#endif


//----------------------------------------------------------------------------------------------------
//========================================== Class MinNode ===========================================
//----------------------------------------------------------------------------------------------------

class CMinNode
{
    public:

        friend class CMinList;

        // Constructor and destructor.

        CMinNode() : pSucc(NULL), pPred(NULL)    {}
        ~CMinNode() {
            if (IsLinked() != FALSE)
            {
                pPred->pSucc = pSucc;           // Unlink the node before deleting it.
                pSucc->pPred = pPred;
            }
        }

        // Accessors

        CMinNode *Next() const
        {
            return ((pSucc->pSucc != NULL) ? pSucc : NULL);
        }

        CMinNode *Pred() const
        {
            return ((pPred->pPred != NULL) ? pPred : NULL);
        }

        // Control.

        int IsLinked() const {return ((int) pSucc | (int) pPred);}
        int IsLast()   const {return (pSucc->pSucc == NULL);}
        int IsFirst()  const {return (pPred->pPred == NULL);}

        operator int()      const   {return ((int) pSucc | (int) pPred);}
        int operator !()    const   {return !((int) pSucc | (int) pPred);}

        // Nodes management.

        void Remove();
        void Insert(CMinNode *node);

    protected:

        CMinNode & operator = (const CMinNode &);     // Not implemented.
        CMinNode(const CMinNode &);                   // Not implemented.

        void ResetLinks()   {pSucc = pPred = NULL;}

    private:

        CMinNode *pSucc;
        CMinNode *pPred;
};


/*----------------------------------------------------------------------------------------------------*/

// inline CMinNode::~CMinNode()
// {
//     if (IsLinked() != FALSE)
//     {
//         pPred->pSucc = pSucc;           // Unlink the node before deleting it.
//         pSucc->pPred = pPred;
//     }
// }

inline void CMinNode::Insert(CMinNode *node)
{
    pPred = node;                       // Insert the current node after the node given.
    pSucc = node->pSucc;
    pSucc->pPred = node->pSucc = this;
}

inline void CMinNode::Remove()
{
    pPred->pSucc = pSucc;
    pSucc->pPred = pPred;
    ResetLinks();
}


//----------------------------------------------------------------------------------------------------
//=========================================== Class Node =============================================
//----------------------------------------------------------------------------------------------------

#ifndef STRING
typedef const char *STRING;
#endif


class CNode : public CMinNode
{
    public:

        // Constructor and destructor.

        CNode(STRING name = NULL, UBYTE type = NT_USER, BYTE pri = 0)
            : pcName(name), bPri(pri), bType(type) {}

        // Accessors

        STRING NodeName() const         {return pcName;}
        void   NodeName(STRING name)    {pcName = name;}

        UBYTE NodeType() const          {return bType;}
        void  NodeType(UBYTE type)      {bType = type;}

        BYTE  NodePri() const           {return bPri;}
        void  NodePri(BYTE pri)         {bPri = pri;}

    protected:

        CNode & operator = (const CNode &);       // Not implemented.
        CNode(const CNode &);                     // Not implemented.

    private:

        UBYTE       bType;
        BYTE        bPri;
        STRING      pcName;
};


//----------------------------------------------------------------------------------------------------
//========================================= Class MinList ============================================
//----------------------------------------------------------------------------------------------------

class CMinList
{
    public:

        // Constructor and destructor.

        CMinList() : pTail(NULL)         {ResetList();}

        ~CMinList()
        {
            CMinNode *p2;
            CMinNode *p1 = (CMinNode *) this;

            while ((p2 = p1->Next()) != NULL)
            {
                p1->ResetLinks();       // Unlink all nodes before freeing the list.
                p1 = p2;
            }
        }

        // Control

        int IsEmpty() const         {return (poTailPred == (CMinNode *) this);}

        operator int ()  const      {return (poTailPred == (CMinNode *) this);}
        int operator !() const      {return (poTailPred != (CMinNode *) this);}

        // Manipulators.

        CMinNode *RemHead();
        CMinNode *RemTail();

        void Enqueue(CNode *node);
        void AddHead(CMinNode *node)     {node->Insert(poHead);}
        void AddTail(CMinNode *node)     {node->Insert(poTailPred);}

        CNode *FindName(STRING name) const;

        static CNode *FindName(const CNode *node, STRING name) const;

        // Misc.

        CMinNode *First() const  {return ( (IsEmpty() != FALSE) ? NULL : poHead);}
        CMinNode *Last()  const  {return ( (IsEmpty() != FALSE) ? NULL : poTailPred);}

    protected:

        CMinList(const CMinList &);                   // Not implemented.
        CMinList & operator = (const CMinList &);     // Not implemented.

    private:

        CMinNode *poHead;
        CMinNode *const pTail;
        CMinNode *poTailPred;

        void ResetList() {poHead = (CMinNode *) &pTail; poTailPred = (CMinNode *) &poHead;}
};

/*----------------------------------------------------------------------------------------------------*/

inline CMinNode * CMinList::RemHead()
{
    CMinNode *p = NULL;

    if (IsEmpty() == FALSE)
    {
        p = poHead;
        p->Remove();
    }
    return (p);
}


inline CMinNode * CMinList::RemTail()
{
    CMinNode *p = NULL;

    if (IsEmpty() == FALSE)
    {
        p = poTailPred,
        p->Remove();
    }
    return (p);
}


inline void CMinList::Enqueue(CNode *node)
{
    ::Enqueue((List *) this, (Node *) node);
}


inline CNode *CMinList::FindName(STRING name) const
{
    return (CNode *) ::FindName((List *) this, (UBYTE *) name);
}


inline CNode *CMinList::FindName(const CNode *node, STRING name) const
{
    return (CNode *) ::FindName((List *) node, (UBYTE *) name);
}


/*----------------------------------------------------------------------------------------------------*/
/*=========================================== Classe List ============================================*/
/*----------------------------------------------------------------------------------------------------*/

class CList : public CMinList
{
    public:

        CList(UBYTE type = NT_USER) : bType(type)    {}

        UBYTE   Type() const        {return bType;}
        void    Type(UBYTE type)    {bType = type;}

    protected:

        CList &operator = (const CList &);    // Not implemented.
        CList(const CList &);                 // Not implemented.

    private:

        UBYTE   bType;
        UBYTE   bPad;
};


/*----------------------------------------------------------------------------------------------------*/

#endif

