/******************************************************************************/
/*!
\file   stack.cpp
\author Artie Fufkin
\par    email: cooldude234\@hotmail.com
\par    DigiPen login: afufkin
\par    Course: CS170
\par    Assignment #1
\date   7/20/2001
\brief  
  This is the implementation file for all member functions
  of a class called Stack, as specified in specification
  file stack.h.  
  
  Operations include:

  - Add an item to the stack
  - Remove an item from the stack
  - Read item on top of the stack
  - Check to see if the stack is empty
  - Check to see if the stack is full
  - Output the stack to a stream
  - Return the number of items on the stack
  - Return the size of the stack

*/
/******************************************************************************/
#include <iostream> // for I/O
#include <iomanip>  // for I/O manipulators
#include "stack.h"    // the Stack interface


/******************************************************************************/
/*!

  Creates a stack of size MAX_SIZE and initializes private data.

*/
/******************************************************************************/

Stack::Stack()
{
   top = -1;         // Initialize an empty stack
   size = MAX_SIZE;  // Initialize a stack of maximum size.
}


/******************************************************************************/
/*!

  Creates a stack of size 'initial_size' and initializes private data.
  If the 'initial_size' is < 0, then the size of the stack is set to
  0. If 'initial_size' is > \p MAX_SIZE then the size of the stack is
  set to \p MAX_SIZE.
          
  \param initial_size 
    An integer that specifies the maximum size of the stack. 

*/
/******************************************************************************/
Stack::Stack(int initial_size)
{
    // Initialize an empty stack
  top = -1;               

  if (initial_size < 0)
    size = 0;

    // Set stack to maximum size when input size is oversized
  else if (initial_size > MAX_SIZE)
    size = MAX_SIZE;

    // Otherwize, set stack size to input size
  else
    size = initial_size;
} 

/******************************************************************************/
/*!

  Adds an item to the stack. Verifies the stack is not full before
  adding the item. Changes the stack.
          
  \param item
    An integer that is added to the stack.

  \exception char* 
    text message indicating the reason for the exception 
    (push onto a full stack).

*/
/******************************************************************************/
void Stack::pushItem(int item)
{
    // Check if stack is full
  if (isFull())
    throw ("Attempting to push when stack is full.");

    // If stack is not full, increment the top index and add the item
  top = top + 1;              
  items[top] = item;       
}


/******************************************************************************/
/*!

  Removes the item that is at the top of the stack. Verifies the
  stack is not empty before removing the item. Changes the stack.
      
  \return 
    The integer at the top of the stack.

  \exception char* 
    text message indicating the reason for the exception (pop an empty stack).

*/
/******************************************************************************/
int Stack::popItem(void)
{

    // Check if stack is empty
  if (isEmpty())
    throw ("Attempting to pop when stack is empty.");

  int number = items[top]; // Get the value of top item
  top--;                   // Remove the top item
  return number;           // Return the value of top item to caller
}


/******************************************************************************/
/*!

  Returns the integer that is at the top of the stack without
  removing it. 
      
  \return 
    The integer at the top of the stack.

  \attention
    Due to the limited error handling, an empty stack will return 0.
    The caller should check for an empty stack <i>before</i> calling
    this method.

  \todo 
    Add better error handling (throw an exception).

*/
/******************************************************************************/
int Stack::peekAtTop(void) const
{
    // Check if stack is empty
  if (isEmpty())
    return 0;        // Return 0 to caller

  return items[top]; // Return the value of top item to caller
}


/******************************************************************************/
/*!

  Checks if the stack is empty.

  \return 
    <b>true</b> if the stack is empty, otherwise, <b>false</b>

*/
/******************************************************************************/
bool Stack::isEmpty(void) const
{
    // if array index is negative,stack is empty
  if (top < 0)
    return true;
  else
    return false;
}


/******************************************************************************/
/*!

  Checks if the stack is full.

  \return 
    <b>true</b> if the stack is full, otherwise, <b>false</b>

\brief
    <img src="http://www.digipen.edu/~mmead/images/HomerFace-1.gif">
    <br>
    Mmmm... A full stack....

*/
/******************************************************************************/
bool Stack::isFull(void) const
{
    // if array index is greater or equal to (size - 1),stack is full
  if (top >= size - 1)
    return true;
  else
    return false;
}


/******************************************************************************/
/*!

  Prints out the contents of the stack to the screen.

*/
/******************************************************************************/
void Stack::print(void) const
{
    // call the general-purpose version
  print(std::cout, 6);
}


/******************************************************************************/
/*!

  Prints out the contents of the stack to a stream provided by the user.


  \param stream
    The destination of the output.

  \param width
    The width of the fields written on the stream.

*/
/******************************************************************************/
void Stack::print(std::ostream &stream, int width) const
{
    // index of array
  int i;       

    // Print out all items in the stack and set width to 6
  for (i = 0; i<= top; i++)
    stream << std::setw(width) << items[i];
  stream << std::endl;
}



/******************************************************************************/
/*!

  Returns the number of items on the stack

  \return 
    The number of items on the stack

*/
/******************************************************************************/
int Stack::getCount(void) const
{
    // Number of items is the top index plus one
  return (top + 1);
}


/******************************************************************************/
/*!

  Returns the size of the stack

  \return 
    The size of the stack

*/
/******************************************************************************/
int Stack::getSize(void) const
{
    // Returns size from private part of class
  return size;    
}