
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 ArrayStacksAndQueues {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {
        Stack<Integer> intStack = new ArrayStack<Integer>();
        Queue<Integer> intQueue = new ArrayQueue<Integer>();
        for (int i = 0; i < 10; i++) {
            intStack.push(i);
            intQueue.add(i);
        }// end for
        String out = "";
        while (!intQueue.isEmpty()) {
            out += "    " + intStack.pop() + "        " + intQueue.remove() + "\n";
        }// end while
        JOptionPane.showMessageDialog(null, out);
        intQueue.add(37);
        intQueue.add(373);
        intQueue.add(73);
        out = "";
        while (!intQueue.isEmpty()) {
            out += intQueue.remove() + "\n";
        }// end while
        JOptionPane.showMessageDialog(null, out);
        Scanner fileScanner = new Scanner(new File("src/ArrayStacksAndQueues.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));
        stringQ.remove();
    }
}

class ArrayStack<T> implements Stack<T> {

    T[] stack;
    int top;

    public ArrayStack() {
        stack = (T[]) new Object[5];
        top = -1;
    }

    public boolean isEmpty() {
        return top == -1;
    }

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

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

    public void push(T item) {
        if (top + 1 == stack.length) {
            increaseCapacity();
        }
        top++;
        stack[top] = item;
    }

    void increaseCapacity() {
        T[] save = stack;
        stack = (T[]) new Object[2 * stack.length + 1];
        for (int i = 0; i < save.length; i++) {
            stack[i] = save[i];
        }
    }
}

class ArrayQueue<T> implements Queue<T> {

    T[] queue;
    int front;
    int back;

    public ArrayQueue() {
        queue = (T[]) new Object[5];
        front = 0;
        back = queue.length - 1;
    }

    public boolean isEmpty() {
        return (back + 1) % queue.length == front;
    }

    public T peek() {
        if (this.isEmpty()) {
            throw new NoSuchElementException();
        }
        return queue[front];
    }

    public T remove() {
        if (this.isEmpty()) {
            throw new NoSuchElementException();
        }
        T save = queue[front];
        front = (front + 1) % queue.length;
        return save;
    }

    public void add(T item) {
        if ((back + 2) % queue.length == front) {
            increaseCapacity();
        }
        back = (back + 1) % queue.length;
        queue[back] = item;
    }

    void increaseCapacity() {
        T[] save = queue;
        queue = (T[]) new Object[2 * queue.length + 1];
        int j = front;
        for (int i = 0; i < save.length; i++) {
            queue[i] = save[j];
            j = (j + 1) % save.length;
            front = 0;
            back = save.length - 2;
        }
    }
}

