class Deque<T> {

    private var head:Node<T>? = null

    fun first():Node<T>? = head

    fun last(): Node<T>? {
        var node = head
        if (node != null){
            while (node?.next != null) {
                node = node.next
            }
            return node
        } else {
            return null
        }
    }

    fun nodeAtIndex(index: Int) : Node<T>? {
        if (index >= 0) {
            var node = head
            var i = index
            while (node != null) {
                if (i == 0) return node
                i -= 1
                node = node.next
            }
        }
        return null
    }

    fun push(value: T) {
        val newNode = Node(value)

        val lastNode = this.last()
        if (lastNode != null) {
            newNode.previous = lastNode
            lastNode.next = newNode
        } else {
            head = newNode
        }
    }

    fun unshift(value: T) {
        val newNode = Node(value)

        val firstNode = this.first()
        if (firstNode != null){
            newNode.next = firstNode
            firstNode.previous = newNode
            head = newNode
        } else {
            head = newNode
        }
    }

    fun removeNode(node: Node<T>):T {
        val prev = node.previous
        val next = node.next

        if (prev != null) {
            prev.next = next
        } else {
            head = next
        }
        next?.previous = prev

        node.previous = null
        node.next = null

        return node.value
    }

    fun pop() : T? {
        val last = this.last()
        if (last != null) {
            return removeNode(last)
        } else {
            return null
        }
    }

    fun shift(): T? {
        return removeAtIndex(0)
    }

    fun removeAtIndex(index: Int):T? {
        val node = nodeAtIndex(index)
        if (node != null) {
            return removeNode(node)
        } else {
            return null
        }
    }
}

class Node<T>(value: T){
    var value:T = value
    var next: Node<T>? = null
    var previous:Node<T>? = null
}