#ifndef __INC_DLList_cc__
#define __INC_DLList_cc__


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

using namespace std;



DLList::DLList() {
    first = NULL;
    last = NULL;
    current = NULL;
}

void DLList::append(int 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
}

void DLList::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
    }
}

void DLList::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
}

void DLList::toStart() {
    current = first;
}

void DLList::toEnd() {
    current = last;
}

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

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

int DLList::read() {
    if (current == NULL) 
      return -1;
    return current->value;
}

int DLList::readNext() {
    int value = read();                     // Wert lesen
    next();                                 // Cursor weiterschieben
    return value;                           // Wert zurueckliefern
}

int DLList::readPrev() {
    int value = read();
    prev();
    return value;
}

bool DLList::isNonEmpty() {
    return (last != NULL);
}

bool DLList::isAtEnd() {
    return current == last;
}

bool DLList::isAtStart() {
    return current == first;
}

#endif
