/*  Template of linked list (?)
    Copyright (C) 1999  Sergey Fadeyev, 2:5020/877

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef _LIST_TPL
#define _LIST_TPL

template <class type>
    class list_el {
    public:
        type data;
        list_el *next;
        list_el *prev;
        list_el() { // default constructor
            prev=NULL;
            next=NULL;
        }
        list_el(type &c) {
            data=c;
            prev=NULL;
            next=NULL;
        }
        list_el(list_el<type>&c) { // copy constructor
            data=c.data;
            prev=c.prev;
            next=c.prev;
        }
        list_el(list_el<type>*previous) {
            prev=previous;
            next=NULL;
        }
        list_el(list_el<type>*previous,type &c) {
            data=c;
            prev=previous;
            next=NULL;
        }
        list_el(list_el<type>*previous,list_el<type>*next_el) {
            prev=previous;
            next=next_el;
        }
        list_el(list_el<type>*previous,list_el<type>*next_el,type &c) {
            data=c;
            prev=previous;
            next=next_el;
        }

        list_el<type>& operator=(list_el<type>&el) {
            data=el.data;
            return *this;
        }
        int operator==(list_el<type>&el) {
            return data==el.data;
        }
        //char* string(char*buf);
    };

template <class type>
    class list {
    protected:
        list_el<type>* head;
        list_el<type>* current;
    public:
        list() { // default constructor
            head=NULL;
            current=NULL;
        }
        /*list(list&c) { // copy constructor
         list_el<type>* sav_current;

         sav_current=c.current;
         head=new list_el<type>(c.head->data);
         ... // so on, not created yet
         current=c.current;
         }*/
        list(int num) {
            list_el<type>* c_el;

            head=new list_el<type>;
            current=head;
            c_el=head;
            for(int i=1; i<num; i++)
            {
                c_el->next=new list_el<type>(c_el);
                //c_el->next->prev=c_el;
                c_el=c_el->next;
            }
        }

        list_el<type>* next() {
            if((current->next)==NULL)
                return NULL;
            return current=(current->next);
        }
        list_el<type>* prev() {
            if((current->prev)==NULL)
                return NULL;
            return current=(current->prev);
        }
        list_el<type>* curr() {
            return current;
        }
        list_el<type>* curr(list_el<type>* c) {
            return current=c;
        }
        list_el<type>* goto_head() {
            return current=head;
        }
        list_el<type>* add_el(type &inf)
        {
            list_el<type>* c_el;

            //cout<<"Adding new area: "<<inf<<endl;
            if(head!=NULL)
            {
                c_el=head;
                while(c_el->next!=NULL)
                {
                    /*printf("Comparing %s and %s, returned %d\n",inf.echotag,
                     c_el->data.echotag,
                     strcmp(inf.echotag,c_el->data.echotag));*/
                    if(inf<c_el->data)
                    {
                        /*if(c_el->prev==NULL)
                         printf("Adding %s before %s\n",inf.echotag,
                         c_el->data.echotag);
                         else
                         printf("Adding %s between %s and %s\n",inf.echotag,
                         c_el->prev->data.echotag,c_el->data.echotag);*/
                        c_el=new list_el<type>(c_el->prev,c_el);
                        c_el->next->prev=c_el;
                        if(c_el->prev==NULL)
                            head=c_el;
                        else
                            c_el->prev->next=c_el;
                        c_el->data=inf;
                        return c_el;
                    }
                    else
                        c_el=c_el->next;
                }
                /*printf("Comparing %s and %s, returned %d\n",inf.echotag,
                 c_el->data.echotag,
                 strcmp(inf.echotag,c_el->data.echotag));*/
                if(inf<c_el->data)
                {
                    /*if(c_el->prev==NULL)
                     printf("Adding %s before %s\n",inf.echotag,
                     c_el->data.echotag);
                     else
                     printf("Adding %s between %s and %s\n",inf.echotag,
                     c_el->prev->data.echotag,c_el->data.echotag);*/
                    c_el=new list_el<type>(c_el->prev,c_el);
                    c_el->next->prev=c_el;
                    if(c_el->prev==NULL)
                        head=c_el;
                    else
                        c_el->prev->next=c_el;
                    c_el->data=inf;
                    return c_el;
                }
                else
                {
                    /*printf("Adding %s after %s\n",inf.echotag,
                     c_el->data.echotag);*/
                    c_el->next=new list_el<type>(c_el);
                    c_el=c_el->next;
                    c_el->data=inf;
                    return c_el;
                }
            }
            else
            {
                //printf("Adding %s at the head\n",inf.echotag);
                head=new list_el<type>;
                current=head;
                c_el=head;
            }
            c_el->data=inf;
            return c_el;
        }
        list_el<type>* rem_el(list_el<type>* c) {
            if(c==head)
            {
                head=c->next;
            }
            else
            {
                c->prev.next=c.next;
            }
            c->next.prev=c.prev;
            //delete *c;
        }
    };

#endif //define _LIST_TPL
