#include <stdio.h>
#include "string_set.h"

/*
  Example of a traversal function. This will print each member of the set.

  No additional parameters are passed to the traversal function, so `args` is
  ignored.
*/
int
print_set_members(
  RBT_KEY_DATA_T * key_data,
  RBT_KEY_SIZE_T height,
  va_list args
)
{
  if (! RBT_VALUE_IS_NULL(key_data->node->value))
  {
    printf("%.*s\n", (int) key_data->bytes, (char *) key_data->key);
  }
  return 0;
}

int main(int argc, char * * argv)
{
  RBT_NODE_T * set_a, * set_b, * copy;
  int i, x;

  /*
    Create the sets. They are just root nodes.
  */
  set_a = RBT_NODE_NEW();
  set_b = RBT_NODE_NEW();

  /*
    Populate the sets.
  */
  RBT_SET_ADD(set_a, "blue");
  RBT_SET_ADD(set_a, "cyan");
  RBT_SET_ADD(set_a, "green");
  RBT_SET_ADD(set_a, "magenta");
  RBT_SET_ADD(set_a, "red");
  RBT_SET_ADD(set_a, "yellow");

  RBT_SET_ADD(set_b, "blue");
  RBT_SET_ADD(set_b, "green");
  RBT_SET_ADD(set_b, "red");
  RBT_SET_ADD(set_b, "black");
  RBT_SET_ADD(set_b, "white");


  /*
    Print out a tree representation of the set.
  */
//   RBT_NODE_FPRINT(stdout, set_a, 1, 0);



  /*
    List members of set A.
  */
  printf("Members of set A:\n");
  printf("-----------------\n");
  RBT_NODE_TRAVERSE_WITH_KEY(set_a, print_set_members);
  printf("-----------------\n\n");



  /*
    List members of set B.
  */
  printf("Members of set B:\n");
  printf("-----------------\n");
  RBT_NODE_TRAVERSE_WITH_KEY(set_b, print_set_members);
  printf("-----------------\n\n");



  /*
    List members of the union of set A and set B.
  */
  copy = RBT_SET_UNION(set_a, set_b);
  printf("The union of sets A and B:\n");
  printf("--------------------------\n");
  RBT_NODE_TRAVERSE_WITH_KEY(copy, print_set_members);
  printf("--------------------------\n");
  /*
    Check if the previous set is a subset of set A or B.
  */
  if (RBT_SET_IS_SUBSET(copy, set_a))
  {
    printf("The previous set is a subset of set A\n");
  }
  if (RBT_SET_IS_SUBSET(copy, set_b))
  {
    printf("The previous set is a subset of set B\n");
  }
  printf("\n");
  RBT_NODE_FREE(copy);



  /*
    List members of the exclusive disjunction of set A and set B.
  */
  copy = RBT_SET_EXCLUSIVE_DISJUNCTION(set_a, set_b);
  printf("The exclusive disjunction of sets A and B:\n");
  printf("------------------------------------------\n");
  RBT_NODE_TRAVERSE_WITH_KEY(copy, print_set_members);
  printf("------------------------------------------\n");
  /*
    Check if the previous set is a subset of set A or B.
  */
  if (RBT_SET_IS_SUBSET(copy, set_a))
  {
    printf("The previous set is a subset of set A\n");
  }
  if (RBT_SET_IS_SUBSET(copy, set_b))
  {
    printf("The previous set is a subset of set B\n");
  }
  printf("\n");
  RBT_NODE_FREE(copy);



  /*
    List members of the intersection of set A and set B.
  */
  copy = RBT_SET_INTERSECTION(set_a, set_b);
  printf("The intersection of sets A and B:\n");
  printf("---------------------------------\n");
  RBT_NODE_TRAVERSE_WITH_KEY(copy, print_set_members);
  printf("---------------------------------\n");
  /*
    Check if the previous set is a subset of set A or B.
  */
  if (RBT_SET_IS_SUBSET(copy, set_a))
  {
    printf("The previous set is a subset of set A\n");
  }
  if (RBT_SET_IS_SUBSET(copy, set_b))
  {
    printf("The previous set is a subset of set B\n");
  }
  printf("\n");
//   RBT_NODE_FREE(copy);





  if (argc > 1)
  {
    printf("Testing command-line arguments for set membership:\n");
    printf("--------------------------------------------------\n");
  }
  else
  {
    printf("There are no command-line arguments to test for set membership.\n");
  }
  for (i = 1; i < argc; i++)
  {
    x = 0;
    if (RBT_SET_INCLUDES(set_a, argv[i]))
    {
      x += 1;
    }
    if (RBT_SET_INCLUDES(set_b, argv[i]))
    {
      x += 2;
    }
    switch (x)
    {
      case 3:
        printf("\"%s\" is a member of both set A and set B\n", argv[i]);
        break;
      case 2:
        printf("\"%s\" is a member of set B\n", argv[i]);
        break;
      case 1:
        printf("\"%s\" is a member of set A\n", argv[i]);
        break;
      case 0:
        printf("\"%s\" is not a member of any set\n", argv[i]);
        break;
    }
  }
  if (argc > 1)
  {
    printf("--------------------------------------------------\n");
  }

  RBT_NODE_FREE(set_a);
  RBT_NODE_FREE(set_b);
  RBT_NODE_FREE(copy);
  RBT_NODE_CACHE_FREE();

  printf("done\n");
  return 0;
}