package com.hithomelabs.princeton1.module4;

import javax.annotation.Nonnull;
import java.util.Iterator;

// Creating a concrete linked Implementation of Stack
public class LinkedStack<E> extends Stack<E>{

    static class Node<E>{
        E data;
        Node<E> next;

        Node(E data) {
            this.data = data;
            this.next = null;
        }
    }

    Node<E> head = null;
    Node<E> endPtr = null;
    int stackLength = 0;

    @Override
    public boolean isEmpty() {
        return head == null;
    }

    @Override
    public void push(E element) {
        Node<E> new_node = new Node<E>(element);
        if(stackLength == 0)
            head = new_node;
        else
            endPtr.next = new_node;
        endPtr = new_node;
        stackLength++;
    }

    @Override
    public E pop() {
        if(stackLength == 0)
            return null;
        if(stackLength == 1)
            head = null;
        Node<E> secondLastPtr = head;
        while(secondLastPtr!=null && secondLastPtr.next != endPtr && secondLastPtr.next!=null)
            secondLastPtr = secondLastPtr.next;
        E currentValue = endPtr.data;
        endPtr.next = null;
        endPtr = secondLastPtr;
        stackLength--;
        return currentValue;
    }

    @Override
    public int size() {
        return stackLength;
    }

    @Nonnull
    @Override
    public Iterator<E> iterator() {
        return new LinkedlistIterator();
    }

    private class LinkedlistIterator implements Iterator<E>{

        Node<E> iteratorPtr = head;

        @Override
        public boolean hasNext() {
            return iteratorPtr.next != null;
        }

        @Override
        public E next() {
            E currentValue = iteratorPtr.data;
            iteratorPtr = iteratorPtr.next;
            return currentValue;
        }
    }
}
