#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "moviedb.h"
#include "tree.h"


void TreeInitialize(Tree *tree) {
	tree->root=NULL;
	tree->count=0;
	}

/* Allocate a new node, assigning it the value of 'str' and initialize
   the count to 1. */

TreeNode* new_tree_node(char *str) {
	TreeNode *newnode;

	newnode = (TreeNode*) malloc (sizeof(TreeNode));
	if (newnode==NULL) {
		fprintf(stderr, "new_tree_node: malloc failed.\n");
		exit(1);
		}	
	newnode->text=strdup(str);
	if (newnode->text==NULL) {
		fprintf(stderr, "new_tree_node: malloc failed.\n");
		exit(1);
		}	
	newnode->count=1;
	newnode->left=NULL;
	newnode->right=NULL;

	return newnode;
	}



/* Insert a text value into the tree - if the value already exists, increment
   the count for that node. */

void TreeInsert(Tree *tree, char *str) {
	TreeNode *newnode, *x, *y;

	/* with an emty tree just insert a new node */
	if (tree->root==NULL) {
		tree->root = new_tree_node(str);
		tree->count++;
		return;
		}

	/* search the tree */
	y=NULL;
	x=tree->root;
	while (x != NULL) {
		if (strcmp(x->text, str)==0) {
			x->count++;
			return;
			}
		y=x;
		if (strcmp(str,x->text)<0)
			x = x->left;
		else
			x = x->right;
		}

	/* str doesn't yet exist in tree - add it in */

	newnode=new_tree_node(str);
	if (strcmp(str, y->text)<0)
		y->left=newnode;
	else
		y->right=newnode;
	tree->count++;
	}


/* Print the entire tree in sorted order */

void SubTreePrint(TreeNode *subtree) {
	if (subtree!=NULL) {
		SubTreePrint(subtree->left);
		printf("%s: %d\n", subtree->text, subtree->count);
		SubTreePrint(subtree->right);
		}
	}

void TreePrint(Tree *tree) {
	SubTreePrint(tree->root);
	}



/* Recursively delete the tree. */

void SubTreeDelete(TreeNode *subtree) {
	if (subtree!=NULL) {
		SubTreeDelete(subtree->left);
		SubTreeDelete(subtree->right);
		free(subtree->text);
		free(subtree);
		}
	}

void TreeDelete(Tree *tree) {
	SubTreeDelete(tree->root);
	tree->root=NULL;
	tree->count=0;
	}



/* Return the number of nodes whose count is at least n. */

int TreeCount(TreeNode *node, int n) {
	if (node==NULL)
		return 0;
	return TreeCount(node->left, n) + 
		TreeCount(node->right, n)  +
		((node->count >= n) ? 1 : 0);
	}



int SubTreeToArray(char **array, TreeNode *subtree, int pos, int n) {
	char line [ MXLINELEN ] ;
	int added=0;

	if (subtree!=NULL) {
		added = SubTreeToArray(array, subtree->left, pos, n);
		if (subtree->count >= n) {
			sprintf(line, "%s (%d)", subtree->text, subtree->count);
			array[pos+added]=strdup(line);
			added++;
			}
		added += SubTreeToArray(array, subtree->right, pos+added, n);
		}
	return added;
	}



/* Create a linear array of pointers to char which point to each of the
   text items in the tree which have a count of 'n' or greater.  
   It is the responsibility of the calling application to free the allocated 
   memory. */

char** TreeToArray(Tree *tree, int n) {
	char **array;
	int size;

	size = TreeCount(tree->root, n);
	array = malloc (sizeof(char*) * (size+1));
	SubTreeToArray(array, tree->root, 0, n);
	array[size] = NULL;
	return array;
	}
