package cpsc2150.MyDeque;

import java.util.Scanner;

/**
 * Class that contains a main method for use with IDeque and classes that implement IDeque.
 * Uses Integers for Deque objects.
 */
public class DequeApp {

    /**
     * Main method for DequeApp that asks a user which type of deque
     * they'd like to use and adds some integers to the deque.
     *
     * @param args Command-line arguments
     *
     * @post
     *      [ a list of integers added to a deque will be printed ]
     */
    public static void main(String[] args) {

        IDeque<Integer> q;

        // Prompt for input
        System.out.println("Enter 1 for array implementation or 2 for List implementation");

        Scanner input = new Scanner(System.in);
        // Take in input
        int choice = Integer.parseInt(input.nextLine());

        // Verify that user entered 1 or 2
        while (choice != 1 && choice != 2) {

            // Prompt for input again
            System.out.println("Enter 1 for array implementation or 2 for List implementation");
            // Take in input again
            choice = input.nextInt();

        }

        // If choice is 1, initialize ArrayDeque
        if (choice == 1) {

            q = new ArrayDeque<Integer>();

          // If choice is 2, initialize ListDeque
        } else {

            q = new ListDeque<Integer>();

        }

        int menuChoice = 0;
        // Loop while menuChoice is not valid (loop logic handles menuChoice at end)
        while (menuChoice < 1 || menuChoice > 12) {

            // Call helper function printMenu
            printMenu();

            // Take in menuChoice
            menuChoice = Integer.parseInt(input.nextLine());

            // Switch statement for menuChoice
            switch (menuChoice) {

                // Add to the end of the deque
                case 1:
                    // Make sure deque can take another integer
                    if (q.length() < IDeque.MAX_LENGTH) {

                        System.out.println("What integer to enqueue to the end of the Deque?");

                        q.enqueue(Integer.parseInt(input.nextLine()));

                    } else {

                        System.out.println("Deque is full!");

                    }
                    break;

                // Add to front of deque
                case 2:
                    // Make sure deque can take another integer
                    if (q.length() < IDeque.MAX_LENGTH) {

                        System.out.println("What integer to inject to the front of the Deque?");

                        q.inject(Integer.parseInt(input.nextLine()));

                    } else {

                        System.out.println("Deque is full!");

                    }
                    break;

                // Remove from front of deque
                case 3:
                    // Make sure deque is not empty
                    if (q.length() > 0) {

                        System.out.println("Integer at the front: " + q.dequeue());

                    } else {

                        System.out.println("Deque is empty!");

                    }
                    break;

                // Remove from end of deque
                case 4:
                    // Make sure deque is not empty
                    if (q.length() > 0) {

                        System.out.println("Integer at the end: " + q.removeLast());

                    } else {

                        System.out.println("Deque is empty!");

                    }
                    break;

                // Peek from front of deque
                case 5:
                    // Make sure deque is not empty
                    if (q.length() > 0) {

                        System.out.println("Peek: " + q.peek());

                    } else {

                        System.out.println("Deque is empty!");

                    }
                    break;

                // Peek from end of deque
                case 6:
                    // Make sure deque is not empty
                    if (q.length() > 0) {

                        System.out.println("EndOfDeque: " + q.endOfDeque());

                    } else {

                        System.out.println("Deque is empty!");

                    }
                    break;

                // Insert to a position in deque
                case 7:
                    // Make sure deque can take another integer
                    if (q.length() < IDeque.MAX_LENGTH) {

                        System.out.println("What integer to insert to the Deque?");
                        int num = Integer.parseInt(input.nextLine());

                        System.out.println("What position to insert in?");
                        int pos = Integer.parseInt(input.nextLine());

                        // Loop until position is valid
                        while (pos < 1 || pos > q.length()) {

                            System.out.println("Not a valid position in the Deque!");

                            System.out.println("What position to insert in?");
                            pos = Integer.parseInt(input.nextLine());

                        }

                        q.insert(num, pos);

                    } else {

                        System.out.println("Deque is full!");

                    }
                    break;

                // Remove from position in deque
                case 8:
                    // Make sure deque is not empty
                    if (q.length() > 0) {

                        System.out.println("What position to remove from the Deque?");
                        int pos = Integer.parseInt(input.nextLine());

                        // Loop until position is valid
                        while (pos < 1 || pos > q.length()) {

                            System.out.println("Not a valid position in the Deque!");

                            System.out.println("What position to remove from the Deque?");
                            pos = Integer.parseInt(input.nextLine());

                        }

                        System.out.println(q.remove(pos) + " was at position " + pos + " in the Deque.");

                    } else {

                        System.out.println("Deque is empty!");

                    }
                    break;

                // Get a position in deque
                case 9:
                    // Make sure deque is not empty
                    if (q.length() > 0) {

                        System.out.println("What position to get from the Deque?");
                        int pos = Integer.parseInt(input.nextLine());

                        // Loop until position is valid
                        while (pos < 1 || pos > q.length()) {

                            System.out.println("Not a valid position in the Deque!");

                            System.out.println("What position to get from the Deque?");
                            pos = Integer.parseInt(input.nextLine());

                        }

                        System.out.println(q.get(pos) + " is at position " + pos + " in the Deque.");

                    } else {

                        System.out.println("Deque is empty!");

                    }
                    break;

                // Get the length of deque
                case 10:
                    System.out.println("Length of Deque: " + q.length());
                    break;

                // Clear the deque
                case 11:
                    q.clear();
                    System.out.println("Deque is now empty!");
                    break;

                // Quit
                case 12:
                    // Return early
                    return;

                // Non-valid options
                default:
                    System.out.println("Not a valid option!");

            }

            // Print deque
            System.out.println("Deque is:");
            System.out.println(q.toString());

            // Set menuChoice back to zero to loop again
            menuChoice = 0;

        }

    }

    /**
     * Function that prints the program menu.
     *
     * @post
     *      [ the menu will be printed ]
     */
    private static void printMenu() {

        System.out.println();
        System.out.println("Select an option:");
        System.out.println("1. Add to the end of the Deque");
        System.out.println("2. Add to the front of the Deque");
        System.out.println("3. Remove from the front of the Deque");
        System.out.println("4. Remove from the end of the Deque");
        System.out.println("5. Peek from the front of the Deque");
        System.out.println("6. Peek from the end of the Deque");
        System.out.println("7. Insert to a position in the Deque");
        System.out.println("8. Remove from a position in the Deque");
        System.out.println("9. Get a position in the Deque");
        System.out.println("10. Get the length of the Deque");
        System.out.println("11. Clear the Deque");
        System.out.println("12. Quit");

    }

}
