#ifndef __INC_GenDLList_cc__
#define __INC_GenDLList_cc__

/* ADT Doppelt verkettete Liste (Double Linked List) -- implementation */
#include <iostream>
#include "GenDLList.h"

using namespace std;

template<class Value_T>
GenDLList<Value_T>::GenDLList() {
    first = NULL;
    last = NULL;
    current = NULL;
}

template<class Value_T>
void GenDLList<Value_T>::append(Value_T x) {
    ListItem *item = new ListItem();      // Erzeuge neues Listenelement
    item->value = x;                      // ... und initialisiere es.
    item->next = NULL; item->prev = NULL;
    if (first == NULL) {                  // Liste noch leer?
      first = item; current = item;         // Neues Element ist jetzt erstes
    } else {
      last->next = item; item->prev = last; // Neues Element hinten anhaengen
    }
    last = item;                          // Das neue Element ist das letzte
}

template<class Value_T>
void GenDLList<Value_T>::deleteCurrent() {
    if (current == NULL) {
      return;
    } if (current == first) {             // Soll das erste Element geloescht werden?
      first = first->next;                  // Erstes ueberspringen
      if (first!=NULL) {                    // letztes Element?
         first->prev = NULL;               // Es gibt keinen Vorgaenger
      } else {
         last=NULL;                        // Liste ist leer
      } 
      delete current;                       // Element loeschen
      current = first;                      // Cursor richtig setzen
    } else if (current == last) {           // Soll das letzte Element geloescht werden?
      last = last->prev;                    // Letztes ueberspringen
      last->next = NULL;                    // Es gibt keinen Nachfolger
      delete current;                       // Element loeschen
      current = last;                       // Cursor richtig setzen
    } else {                                
      ListItem *prevItem = current->prev;   // Einen Anker behalten
      prevItem->next = current->next;       // Aktuelles Element überspringen
      current->next->prev = prevItem;       // und noch mal
      delete current;                       // Element loeschen
      current = prevItem;                   // Vorheriges Element ist letztes
    }
}

template<class Value_T>
void GenDLList<Value_T>::deleteIndex(int index) {
    ListItem *oldCurrent = current;       // Aktuellen Cursor merken
    toStart();                            // Cursor auf Anfang setzen
    while (index > 0) {                   // An die passende Stelle iterieren
      next();                               // Mit readNext Cursor weiterschieben
      index--;                              // Zaehler anpassen
    }
    deleteCurrent();                      // Element loeschen
    current = oldCurrent;                 // Alten Cursor restaurieren
}

template<class Value_T>
void GenDLList<Value_T>::toStart() {
    current = first;
}

template<class Value_T>
void GenDLList<Value_T>::toEnd() {
    current = last;
}

template<class Value_T>
void GenDLList<Value_T>::next() {
    if (current == NULL) {
      cerr << "GenDLList::next: current == NULL" << endl; return;    
    }
    if (current == last) {
      cerr << "GenDLList::next: am Ende der Liste" << endl; return;
    }
    current = current->next;
}

template<class Value_T>
void GenDLList<Value_T>::prev() {
    if (current == NULL) {
      cerr << "GenDLList::prev: current == NULL" << endl; return;
    }
    if (current == first) {
      cerr << "GenDLList::next: am Anfang der Liste" << endl; return;
    }
    current = current->prev;
}

template<class Value_T>
Value_T GenDLList<Value_T>::read() {
    if (current == NULL) 
      return NULL;
    return current->value;
}

template<class Value_T>
Value_T GenDLList<Value_T>::readNext() {
    Value_T value = read();                 // Wert lesen
    next();                                 // Cursor weiterschieben
    return value;                           // Wert zurueckliefern
}

template<class Value_T>
Value_T GenDLList<Value_T>::readPrev() {
    Value_T value = read();
    prev();
    return value;
}

template<class Value_T>
bool GenDLList<Value_T>::isNonEmpty() {
    return (last != NULL);
}

template<class Value_T>
bool GenDLList<Value_T>::isAtEnd() {
    return current == last;
}

template<class Value_T>
bool GenDLList<Value_T>::isAtStart() {
    return current == first;
}

#endif