/*
 * Copyright 2011 Steven Gribble
 *
 *  This file is the solution to an exercise problem posed during
 *  one of the UW CSE 333 lectures (333exercises).
 *
 *  333exercises is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  333exercises is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with 333exercises.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "bst.h"

// Lecture 5, exercise 2
//
// Implement and test a binary search tree
//   - http://en.wikipedia.org/wiki/Binary_search_tree
//   - don’t worry about making it balanced
//   - implement key insert( ) and lookup( ) functions
//   - implement it as a C module
//      - bst.c, bst.h
//   - implement test_bst.c
//      - contains main( ), tests out your BST

typedef struct bst_el_st {
  int key;
  char value[10];
} BSTElement;

// This helper function is the comparator we provide
// for comparing BSTElement structures.
static int BSTElComparator(void *el1, void *el2) {
  BSTElement *e1 = (BSTElement *) el1;
  BSTElement *e2 = (BSTElement *) el2;

  if (e1->key > e2->key)
    return 1;
  if (e1->key < e2->key)
    return -1;
  return 0;
}

int main(int argc, char **argv) {
  TreeNode *tree = NULL;
  BSTElement *el, lookupel;

  // Malloc and push in a few elements
  el = (BSTElement *) malloc(sizeof(BSTElement));
  assert(el != NULL);
  el->key = 100;
  snprintf(el->value, 10, "Val 100");
  assert(Insert(tree, el, &BSTElComparator, &tree) == 1);
  assert(Insert(tree, el, &BSTElComparator, &tree) == -1);

  el = (BSTElement *) malloc(sizeof(BSTElement));
  assert(el != NULL);
  el->key = 110;
  snprintf(el->value, 10, "Val 110");
  assert(Insert(tree, el, &BSTElComparator, &tree) == 1);
  assert(Insert(tree, el, &BSTElComparator, &tree) == -1);

  el = (BSTElement *) malloc(sizeof(BSTElement));
  assert(el != NULL);
  el->key = 105;
  snprintf(el->value, 10, "Val 105");
  assert(Insert(tree, el, &BSTElComparator, &tree) == 1);
  assert(Insert(tree, el, &BSTElComparator, &tree) == -1);

  el = (BSTElement *) malloc(sizeof(BSTElement));
  assert(el != NULL);
  el->key = 107;
  snprintf(el->value, 10, "Val 107");
  assert(Insert(tree, el, &BSTElComparator, &tree) == 1);
  assert(Insert(tree, el, &BSTElComparator, &tree) == -1);

  // Do some lookups
  lookupel.key = 105;
  assert(Lookup(tree, (void *) &lookupel, &BSTElComparator,
                (void **) &el) == 1);
  assert(strcmp(el->value, "Val 105") == 0);

  lookupel.key = 107;
  assert(Lookup(tree, &lookupel, &BSTElComparator,
                (void **) &el) == 1);
  assert(strcmp(el->value, "Val 107") == 0);

  lookupel.key = 100;
  assert(Lookup(tree, &lookupel, &BSTElComparator,
                (void **) &el) == 1);
  assert(strcmp(el->value, "Val 100") == 0);

  lookupel.key = 110;
  assert(Lookup(tree, &lookupel, &BSTElComparator,
                (void **) &el) == 1);
  assert(strcmp(el->value, "Val 110") == 0);

  // Try a lookup that should fail.
  lookupel.key = 10;
  assert(Lookup(tree, &lookupel, &BSTElComparator,
                (void **) &el) == 0);

  return EXIT_SUCCESS;
}