#ifndef _LIST_HPP_
#define _LIST_HPP_
#include <iostream>
#include <string>
#define Node node *

template <class T>
class List
{
    typedef struct node
    {
        T data;
        Node pred;
        Node succ;
    } node;

private:
    Node header = new node;
    Node trailer = new node;
    int _size;

protected:
    Node firstInsertN(Node New);
    Node lastInsertN(Node New);
    Node succInsertN(Node old, Node ne);
    Node predInsertN(Node old, Node ne);
    void removeN(Node i);
    Node searchN(int value, int n, Node p);

public:
    int size()
    {
        return _size;
    }
    List();
    void clear();
    Node first() { return header->succ; }
    Node last() { return trailer->pred; }
    T firstInsert(T New);
    T lastInsert(T New);
    T removeLast();
    Node succInsert(Node Old, T New);
    Node predInsert(Node Old, T New);

    int get(int i);
    Node find(int i);
    T remove(T i);

    T operator[](int i)
    {
        Node p = first();
        while (0 < i--)
            p = p->succ;
        return p->data;
    }
};

template <class T>
List<T>::List()
{
    _size = 0;
    header->data = NULL;
    header->succ = trailer;
    header->pred = NULL;

    trailer->data = NULL;
    trailer->succ = NULL;
    trailer->pred = header;
}

template <class T>
void List<T>::clear()
{
    while (0 < _size)
        remove(0);
}

template <class T>
T List<T>::firstInsert(T New)
{
    Node temp = new node;
    temp->data = New;
    temp->pred = header;
    temp->succ = header->succ;
    header->succ = temp;
    temp->succ->pred = temp;
    _size++;
    return New;
}

template <class T>
T List<T>::removeLast()
{
    if (!_size)
        return NULL;

    Node last = trailer->pred;
    T temp = last->data;
    (last->pred)->succ = last->succ;
    (last->succ)->pred = last->pred;
    delete[] last;
    _size--;

    return temp;
}

#endif