#include <string>
#include <iostream>
#include <cstdlib>
#include <stdexcept>
#include "LeakyStack.h"
#include "LeakyStackA.h"
#include "LeakyStackB.h"
#include "InputWrapper.h"

using namespace std;

bool valid(LeakyStack *ls) {
    if (!ls) {
	cout << "The history has not yet been properly initialized." << endl;;
	return(false);
    } else
	return(true);
}


int main(int argc, const char* argv[]) {
    InputWrapper input(argc, argv);   // initialize wrapper for file input

    // is there a limit on the number of lines to read?
    int LIMIT = -1;
    if (argc>2) {
	LIMIT = atoi(argv[2]);
	if (LIMIT < 1) {
	    LIMIT = -1;
	    cout << "Second argument (" << argv[2] << ") ignored." << endl << endl;
	}
    }

    string MENU = "Valid commands include:\n(A)  create or reinitialize with LeakyStackA.\n(B)  create or reinitialize with LeakyStackB.\n(S)  call size.\n(E)  call empty.\n(U)  call push.\n(P)  call pop\n(T)  call top\n(Q)  Quit.";

    bool quit(false);
    int value;
    int i;
    int command(0);
    string answer;
    char choice;

    LeakyStack *LS(NULL);

    cout << MENU << endl;
    do {
	char temp[50];
	sprintf(temp,"\nCommand #%i> ",++command);
	string response = input.generalQuestion(string(temp));
	choice = response[0];

	switch (choice)
	    {
	    case 'a':
	    case 'A':
	    case 'b':
	    case 'B':
		response = input.generalQuestion("Enter a capacity for the history: ");
		value = atoi((response).c_str());
		if (value < 1) {
		    cout << "Invalid capacity.  Aborting command." << endl;
		} else {
		    if (LS) delete LS;
		    if ((choice=='a') || (choice=='A')) {
			LS = new LeakyStackA(value);
			cout <<  "LeakyStackA constructor called with capacity " << value << endl;
		    } else {
			LS = new LeakyStackB(value);
			cout << "LeakyStackB constructor called with capacity " << value << endl;
		    }
		}
		break;

	    case 's':
	    case 'S':
		if (valid(LS)) {
		    i = LS->size();
		    cout << "size( ) returned " << i << endl;
		}
		break;

	    case 'e':
	    case 'E':
		if (valid(LS)) {
		    bool s = LS->empty();
		    cout << "empty( ) returned " << (s ? "true" : "false") << endl;
		}
		break;

	    case 'u':
	    case 'U':
		if (valid(LS))
		    LS->push(input.generalQuestion("Enter item to push: "));
		break;

	    case 'p':
	    case 'P':
		if (valid(LS)) {
		    try {
			LS->pop();
		    } catch (runtime_error e) {
			cout << "pop( ) threw a runtime_error";
			if (LIMIT == -1)
			    cout << ": " << e.what();
			cout << endl;
		    }

		}
		break;

	    case 't':
	    case 'T':
		if (valid(LS)) {
		    try {
			string answer = LS->top();
			cout << "top( ) returned " << answer << endl;
		    } catch (runtime_error e) {
			cout << "top( ) threw a runtime_error";
			if (LIMIT == -1)
			    cout << ": " << e.what();
			cout << endl;
		    }
		}
		break;

	    case 'q':
	    case 'Q':
		quit = true;
		break;

	    default:
		cout << "Unrecognized option: " << choice << endl;
		cout << MENU << endl;
	    }
    } while (!quit  && (LIMIT < 0 || command < LIMIT));
    cout << endl;

    return(0);
}
