#include <iostream>

using namespace std;

#include "DAStack.h"
#include "DAStackExceptions.h"

void testGetTop(ostream & out, const DAStack & stack);

void testPop(ostream & out, DAStack & stack);

int main()
{
  /* Test verifyAllocation when allocation fails */
  /*
  const int LOTS = 1000;
  DAStack lotsOfDAStacks[LOTS];
  cerr << "array created"<<endl;

  int size = 1000000000;
  for (int i=0; i<LOTS; i++)
  {
    lotsOfDAStacks[i]= DAStack(size);
    cerr<< i ;
  }
  */  

  /* Test default constructor, display of maxElements & nextElement */
  DAStack defaultDAStack;

  /* Now test overloaded << */
  cout << "Default stack created that can hold " << DEFAULT << " item(s).\n" << defaultDAStack << endl;

  /* Test explicit value constructor, display of maxElements & nextElement */
  int capacity = 2;
  DAStack explicitDAStack(capacity);

  /* Now test overloaded << */
  cout << "Explicit value DAStack created that can hold " << capacity << " item(s).\n" << explicitDAStack << endl;

  /* Test copy constructor, display of maxElements & nextElement */
  cout << endl;

  DAStack copyDefault(defaultDAStack);
 
  /* Now test overloaded << */
  cout << "Copied default DAStack created that can hold " << DEFAULT << " item(s).\n" << defaultDAStack << endl;

  DAStack copyExplicit(explicitDAStack);

  /* Now test overloaded << */
  cout << "Copied explicit value DAStack created that can hold " << capacity << " item(s).\n" << explicitDAStack << endl;

  /*Test getTop */
  testGetTop(cout, defaultDAStack);
  testGetTop(cout, copyDefault);
  testGetTop(cout, explicitDAStack);
  testGetTop(cout, copyExplicit); 
  cout << endl;

  /* Test push, this will test display also */
  cout << "Finally, we actually add some data . . ." << endl;
  /* Test push */
  for (int i=0, j=DEFAULT*2; i<DEFAULT*2, j!=0; i++,j--)
  {
    defaultDAStack.push(i);
    /* Test overloaded << */
    cout << defaultDAStack << endl;

    copyDefault.push(j);
    /* Test overloaded << */
    cout << copyDefault << endl;
  }

  for (int i=0, j=capacity*2; i<capacity*2, j!=0; i++,j--)
  {
    explicitDAStack.push(i);
    /* Test overloaded << */
    cout << explicitDAStack << endl;

    copyExplicit.push(j);
    /* Test overloaded << */
    cout << copyExplicit << endl;
  }


  /*Test getTop */
  testGetTop(cout, defaultDAStack);
  testGetTop(cout, copyDefault);
  testGetTop(cout, explicitDAStack);
  testGetTop(cout, copyExplicit);
  cout << endl;


  /* Test overloaded = */
  DAStack assignment1(2);  //So it starts out different from default
  assignment1.push(10);
  assignment1.push(20); //So its contents are different from default
  cout << "Originally, assignment1 looks like this: \n" << assignment1 << endl;
  assignment1 = defaultDAStack;
  cout << "After assignment, it looks like this: \n" << assignment1 << endl;

  DAStack assignment2(2);  //So it starts out different from default copy
  assignment2.push(100);
  assignment2.push(200);  //So its contents are different from default
  cout << "Originally, assignment2 looks like this: \n" << assignment2 << endl;
  assignment2 = copyDefault;
  cout << "After assignment, it looks like this: \n" << assignment2 << endl << endl;

  /* Test pop, this will test display also */

  /* Test pop */
  for (int i=0; i<DEFAULT *2; i++)
  {
    defaultDAStack.pop();
    /* Test overloaded << */
    cout << defaultDAStack << endl;

    copyDefault.pop();
    /* Test overloaded << */
    cout << copyDefault << endl;
  }

  testPop(cout, defaultDAStack);
  testPop(cout, copyDefault);

  for (int i=0; i<capacity*2; i++)
  {
    explicitDAStack.pop();
    /* Test overloaded << */
    cout << explicitDAStack << endl;


    copyExplicit.pop();
    /* Test overloaded << */
    cout << copyExplicit << endl;
  }

  testPop(cout, explicitDAStack);
  testPop(cout, copyExplicit); 

  DAStack stack2;
  cout << "Enter contents of stack2, followed by X:  " << endl;
  cin >> stack2;
  cout << "Is list2 empty? " << boolalpha << stack2.isEmpty() << endl;
  cout << "Number of elements = " << stack2.getSize() << endl << stack2 << endl;


  return 0;
}

void testPop(ostream & out, DAStack & stack)
{
  try
  {
    stack.pop();
  }
  catch(Empty e)
  {
    out << "Invocation of " << e.getMessage() << " failed:  stack is empty." << endl;
  }
}

void testGetTop(ostream & out, const DAStack & stack)
{
  try
  {
    Element item = stack.getTop();
    out << "Last item pushed was:  " << item << endl;
  }
  catch(Empty e)
  {
    out << "Invocation of " << e.getMessage() << " failed:  stack is empty." << endl;
  }
}
