
import java.awt.Font;
import java.io.File;
import java.io.IOException;
import java.util.EmptyStackException;
import java.util.NoSuchElementException;
import java.util.Scanner;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 * This is an example for COP3337
 *
 * @author Bill Kraynek
 */
public class LinkedStacksAndQueues {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {
        Stack<Integer> intStack = new LinkedStack<Integer>();
        Queue<Integer> intQueue = new LinkedQueue<Integer>();
        for (int i = 0; i < 10; i++) {
            intStack.push(i);
            intQueue.add(i);
        }// end for
        String out = "";
        while (!intStack.isEmpty()) {
            out += "    " + intStack.pop() + "       " + intQueue.remove() + "\n";
        } // end while
        JOptionPane.showMessageDialog(null, out);
        Scanner fileScanner = new Scanner (new File("src/LinkedStacksAndQueues.java"));
        fileScanner.useDelimiter("[^a-zA-Z]+");
        Queue<String> stringQ = new ArrayQueue<String>();
        Stack<String> stringStack = new ArrayStack<String>();
        int maxWordLength = 0;
        while( fileScanner.hasNext() ) {
            String aWord = fileScanner.next();
            if( aWord.length() > maxWordLength ) maxWordLength = aWord.length();
            stringStack.push(aWord);
            stringQ.add(aWord);
        }// end while
        out = "";
        String blanks = "";
        for( int i = 0; i < maxWordLength + 2; i++ ) blanks += " ";
        while( !stringQ.isEmpty() ) {
            String word = stringStack.pop();
            out += word + blanks.substring(word.length()) + stringQ.remove() + "\n";
        }// end while
        JTextArea outArea = new JTextArea(out,30,2*maxWordLength+4);
        outArea.setFont(new Font(Font.MONOSPACED,Font.BOLD,15));
        JOptionPane.showMessageDialog(null, new JScrollPane(outArea));
        stringStack.pop();
    }
}

class Node<T> {

    T data;
    Node<T> next;

    Node() {
    }

    Node(T data) {
        this.data = data;
    } // end

    Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    } // end

    public String toString() {
        return data + "";
    } // end toString
} // end Node

class LinkedStack<T> implements Stack<T> {

    Node<T> top;

    public LinkedStack() {
        top = null;
    }

    public boolean isEmpty() {
        return top == null;
    }

    public T peek() {
        if( this.isEmpty() ) throw new EmptyStackException();
        return top.data;
    }

    public T pop() {
        if( this.isEmpty() ) throw new EmptyStackException();
        T save = top.data;
        top = top.next;
        return save;
    }

    public void push(T item) {
        top = new Node<T>(item, top);
    }
}


class LinkedQueue<T> implements Queue<T> {

    Node<T> front;
    Node<T> back;

    public LinkedQueue() {
        front = new Node<T>();
        back = front;
    }

    public boolean isEmpty() {
        return front.next == null;
    }

    public T peek() {
        if( this.isEmpty() ) throw new NoSuchElementException();
        return front.next.data;
    }

    public T remove() {
        if( this.isEmpty() ) throw new NoSuchElementException();
        T save = front.next.data;
        front = front.next;
        front.data = null;
        return save;
    }

    public void add(T item) {
        back.next = new Node<T>(item, null);
        back = back.next;
    }
}

