/*
 * test_tree.c
 * This program prepares a binary tree of integers and lets the user execute 
 * commands on this tree.
 */
#include <stdio.h>
#include <stdlib.h>
#include "tree.h"

#define MAX_COMMAND 20

/* A comparison function for two integer pointers: */
int comp_int (const void *p1, const void *p2)
{
  int   n1, n2;

  n1 = *((int *)p1);
  n2 = *((int *)p2);
  return (n2 - n1);
}

/* ------------------------------------------------------------------------
 * The main:
 */
int main ()
{
  int         n_initial_objects;
  int         max_object;
  Tree        *p_tree;
  const Node  *p_node;
  int         *p_num;
  int         num;
  char        command[MAX_COMMAND];
  char        op_code;
  int         i;

  /* Get the number of initial objects in the tree and the maximal
     value for an object. */
  printf ("Please enter the number of initial objects: ");
  scanf ("%d", &n_initial_objects);

  printf ("Please enter the maximal value of an object: ");
  scanf ("%d", &max_object);

  /* Create the tree - note it should own its objects. */
  p_tree = tree_init (comp_int, 1);

  /* Make sure we get different numbers each time. */
  srand (time (NULL));

  /* Insert random numbers to the tree. */
  for (i = 0; i < n_initial_objects; i++)
  {
    p_num = (int *) malloc (sizeof(int));
    *p_num = (int)(max_object * (float)rand() / (float)RAND_MAX);
    tree_insert (p_tree, p_num);
  }

  /* Get the user commands and execute them. */
  do
  {
    /* Get the current command. */
    printf ("Please enter a command (or ? for help): ");
    scanf ("%s", command);

    op_code = toupper (command[0]);

    if (op_code == '?')
    {
      /* Print the legal commands. */
      printf ("i <n> - insert, f <n> - find, d <n> - delete,\n"
              "p - print, r - print reversed, c - clear, q - quit.\n");
    }
    else if (op_code == 'I')
    {
      /* Read a number and insert it to the tree. */
      p_num = (int *) malloc (sizeof(int));
      scanf ("%d", p_num);
      tree_insert (p_tree, p_num);
      printf ("-> %d has been inserted to the tree.\n", *p_num);
    }
    else if (op_code == 'F')
    {
      /* Read a number and try to locate it in the tree. */
      scanf ("%d", &num);
      if (tree_find (p_tree, &num) != NULL)
        printf ("-> %d is in the tree.\n", num);
      else
        printf ("-> %d is not found in the tree.\n", num);
    }
    else if (op_code == 'D')
    {
      /* Read a number and try to delete it from the tree. */
      scanf ("%d", &num);
      if (tree_delete (p_tree, &num))
        printf ("-> %d has been deleted from the tree.\n", num);
      else
        printf ("-> %d is not found in the tree.\n", num);
    }
    else if (op_code == 'P')
    {
      /* Go forward over all tree elements and print them. */
      for (p_node = tree_min (p_tree);
           p_node != NULL;
           p_node = tree_next (p_node))
      {
        p_num = (int *)(p_node->p_object);
        printf ("%d ", *p_num);
      }
      printf ("\n");
    }
    else if (op_code == 'R')
    {
      /* Go backward over all tree elements and print them. */
      for (p_node = tree_max (p_tree);
           p_node != NULL;
           p_node = tree_prev (p_node))
      {
        p_num = (int *)(p_node->p_object);
        printf ("%d ", *p_num);
      }
      printf ("\n");
    }
    else if (op_code == 'C')
    {
      /* Clear the tree (delete all objects). */
      tree_reset (p_tree);
      printf ("-> The tree has been reset.\n");
    }
    else if (op_code != 'Q')
    {
      printf ("Invalid command: %s\n", command);
    }

  } while (op_code != 'Q');

  /* Free the tree. */
  tree_reset (p_tree);
  free (p_tree);

  return (0);
}

