#include <sys/time.h>
#include <string>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include "LeakyStack.h"
#include "LeakyStackA.h"
#include "LeakyStackB.h"
using namespace std;

#define USE_GETTIMEOFDAY      // otherwise relies on clock_t values             

void usage() {
    cout << "Usage: TestEfficiency X N" << endl;
    cout << "       where X is either A or B, and N > 0" << endl;
}


#ifdef USE_GETTIMEOFDAY
double diff(const timeval& start, const timeval& stop) {
    return (stop.tv_sec - start.tv_sec + (stop.tv_usec - start.tv_usec)/1000000.0);
}
#else
double diff(const clock_t& start, const clock_t& stop) {
    return ((double) stop - start)/CLOCKS_PER_SEC;
}
#endif


int main(int argc, const char* argv[]) {

    LeakyStack* LS(NULL);

    if (argc != 3) {
	usage();
    } else {
	int N(-1);
	N = atoi(argv[2]);
	if (N < 1)
	    usage();
	else {
	    switch (argv[1][0])
		{
		case 'a':
		case 'A':
		    LS = new LeakyStackA(N);
		    break;
		case 'b':
		case 'B':
		    LS = new LeakyStackB(N);
		    break;

		default:
		    cout << "First argument must be A or B" << endl;
		    usage();
		}
	    if (LS) {

                // variables to keep track of timing
#ifdef USE_GETTIMEOFDAY
                timeval  start, stop;
                gettimeofday(&start,NULL);
#else
                cout << "Note:  clock granularity on this machine is " << CLOCKS_PER_SEC << " ticks per second." << endl;
                clock_t  start, stop;
                start = clock();
#endif

		for (int k=0; k < 5*N; k++)
		    LS->push("Testing");
		for (int k=0; k < N; k++)
		    LS->pop();

#ifdef USE_GETTIMEOFDAY
                gettimeofday(&stop,NULL);
#else
                stop = clock();
#endif
                double elapsed = diff(start,stop)*1000000/(6*N);
		cout << "Elapsed Time per operation (microseconds): "
                     << setprecision(8) << fixed << elapsed << endl;
	    }
	}
    }
}
