/* This program uses code from "Algorithms in C, Third Edition,"
 *               by Robert Sedgewick, Addison-Wesley, 1998.
 */

#include <stdio.h>
#include <stdlib.h>

#include "lists.h"
#include "stacks.h"


struct stack_struct
{
   int max_size;
   int top_index;
   void ** items;
};

// For the array-based implementation, calling newStack with no arguments
// returns a stack with max_size = 1000. For the list-based representation,
// there is no max_size.
Stack newStack()
{
   return newStack1(1000);
}

Stack newStack1(int max_size)
{
   Stack result = malloc(sizeof(*result));
   result->items = malloc(max_size * sizeof(void*));
   result->max_size = max_size;
   result->top_index = -1;
   return result;
}


void destroyStack(Stack stack)
{
   int i;
   for (i = 0; i <= stack->top_index; i++)
   {
      free(stack->items[i]);
   }
   free(stack->items);
   free(stack);
}

void push(Stack stack, void * content)
{
   if (stack->top_index == stack->max_size - 1)
   {
      printf("error: stack is full, cannot push\n");
      exit(1);
   }
   
   stack->top_index++;
   stack->items[stack->top_index] = content;
}

void * pop(Stack stack)
{
   if (stackEmpty(stack))
   {
      printf("error: stack is empty, cannot pop\n");
      exit(1);
   }

   void * item = stack->items[stack->top_index];
   stack->top_index--;
   return item;
}


int stackEmpty(Stack stack)
{
   return (stack->top_index == -1);
}

void pushInt(Stack stack, int value)
{
   int * content = malloc(sizeof(int));
   *content = value;
   push(stack, content);
}

int popInt(Stack stack)
{
   int * top = (int *) pop(stack);
   int result = *top;
   free(top);
   return result;
}

void printIntStack(Stack stack)
{
   printf("\n");

   int i;
   for (i = stack->top_index; i >= 0; i--)
   {
      int * content = stack->items[i];
      printf("position %d from the top: %d\n", stack->top_index - i, *content);
   }

   printf("\n");
}
