#ifndef DOUBLY_LINKED_LIST_H
#define DOUBLY_LINKED_LIST_H

#include <cassert>
#include <cstddef>
#include "queue.h"

namespace seq
{
   class DoublyLinkedListNode
   {
   public:
      // return a reference to the stored item
      int& get_item() { return this->item; }

      // return pointer to next node, or nullptr if this is the final node
      DoublyLinkedListNode* get_next() const { return this->next; }

      // return pointer to previous node, or nullptr if this is the initial node
      DoublyLinkedListNode* get_prev() const { return this->prev; }

      // overwrite the item stored in this node
      void set_item(int in_item) { this->item = in_item; }

   private:
      int item = 0;
      DoublyLinkedListNode* next = nullptr;
      DoublyLinkedListNode* prev = nullptr;

      // attach a node behind this node
      // if there was a node attached to this previously, it is NOT deleted!
      void set_next(DoublyLinkedListNode* in_next) { this->next = in_next; }

      // attach a node before this node
      // if there was a node attached to this previously, it is NOT deleted!
      void set_prev(DoublyLinkedListNode* in_prev) { this->prev = in_prev; }
      
      friend class DoublyLinkedList;  // allow DoublyLinkedList to access private members
   };
   
   class DoublyLinkedList: public Queue
   {
   public:
      bool empty() const { return (this->head == nullptr); }  // test whether the doubly linked list is empty
      size_t size() const;  // return the size (number of items in the doubly linked list)

      void enqueue(int element);
      int dequeue();

      // return pointer to the head/tail node
      DoublyLinkedListNode* begin() const { return this->head; }
      DoublyLinkedListNode* end() const { return this->tail; }

      void clear() { while(!this->empty()) this->dequeue(); }  // remove all the items from the list
      
      ~DoublyLinkedList() { this->clear(); }

   private:
      DoublyLinkedListNode* head = nullptr;
      DoublyLinkedListNode* tail = nullptr;
   };
}

#endif
