#include <stdio.h>
#include <assert.h>
#include "tree.h"

TreeNode *
_tree_search_hangul (TreeNode *node, unsigned char *hangul);

void
tree_init (Tree *tree)
{
  assert (tree != NULL);
  if (tree->root != NULL){
    /* This function is meant to be called at the very beginnin.
       I'll not take care of this case for now...no time.. */
    
    fprintf (stderr, "I can't initialize non-empty tree");
    exit (-1);
  }

  tree->root = NULL;
}




void
tree_inorder_traverse (TreeNode *node, void *( *func)(void *))
{
  if (node != NULL){
    tree_inorder_traverse (node->left, func);
    func ((void *)node->data);
    tree_inorder_traverse (node->right, func);
  }
}

int
tree_compare_hangul (TreeNode *a, unsigned char *b)
{
  return  strcmp (a->data->hangul, b);
}

TreeNode *
tree_search_hangul (Tree *tree, unsigned char *hangul)
{
  TreeNode *ret_node = NULL;
  ret_node = _tree_search_hangul (tree->root, hangul);
  return ret_node;
}

TreeNode *
_tree_search_hangul (TreeNode *node, unsigned char *hangul)
{
  assert (hangul != NULL);
  if (hangul == NULL)
    return NULL;

  while (node){
    if (!strcmp (node->data->hangul, hangul))
      return node;
    else if (strcmp (node->data->hangul, hangul) > 0)
      node = node->right;
    else
      node = node->left;
  }
  return NULL;
}

/*
TreeNode *
tree_inorder_search_candidates (TreeNode *node, unsigned char *hangul)
{
  TreeNode *ret;
  if (node != NULL){
    if (
    if ((ret = tree_inorder_search_candidates (node->left, hangul)))
      return ret;

    else if ((ret = tree_inorder_search_candidates (node->right, hangul)))
      return ret;
    else 
      ret = tree_inorder_search_candidates (node->right, hangul);


    if (!_utfstr_comp (node->data->hangul, hangul)){
      return node;
    }
    
    
    
  }
}
*/
void
tree_print (Tree *tree, void * (*print_function) (void *))
{
  TreeNode *root = tree->root;
  tree_inorder_traverse (root, print_function);
}

/* I'll do only shallow copy here, under the assumption that
   the tnode passed as an argument is being held by the caller.
   I do this, because this function will be used only create
   dictionary structure, not for general use.
*/
void
tree_shallow_insert (Tree *tree, TreeNode *tnode)
{
  TreeNode *ptr = tree->root ;
  TreeNode *prev;
  
  int comp_return;

  assert (tree != NULL);
  assert (tnode != NULL);

  if (tree == NULL || tnode == NULL){
    fprintf (stderr, "wrong parameter passed\n");
    exit (-1);
  }
  if (!ptr){
    tree->root = tnode;
    return;
  }

  while (ptr){
    prev = ptr;
    comp_return = hhitem_comp (ptr->data, tnode->data);
    if (comp_return < 0)
      ptr = ptr->left;
    else if (comp_return >0)
      ptr = ptr->right;
    else {
      /* no duplication expected, just return */
      return;
    }
  }
  if (hhitem_comp (prev->data, tnode->data) < 0)
    prev->left = tnode;
  else
    prev->right = tnode;
  
}

/* this function assumes data are sorted already */
void
tree_build_from_array (Tree *tree, TreeNode *data, int first, int last)
{
  int middle;
  if (first <= last){
    middle = (first + last) / 2;
    tree_shallow_insert (tree, data + middle);
    tree_build_from_array (tree, data, first, middle - 1);
    tree_build_from_array (tree, data, middle + 1, last);
  }
    
}


/* this returns new TreeNode.
   this does only shallow copy,
   thus HHEntry passed as argument should always be there
*/
TreeNode *
tree_node_shallow_new (HHEntry data)
{
  TreeNode *p_newnode =
    (TreeNode *) calloc (1, sizeof (TreeNode));
  p_newnode->data = data;
  return p_newnode;
}

