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

#include "BTnode.h"

BTnode_t* create_node(int val) {
  BTnode_t* newNode = (BTnode_t*) malloc(sizeof(BTnode_t));
  newNode->value = val;
  newNode->left = NULL;
  newNode->right = NULL;
  newNode->parent = NULL;
  return newNode;
}

void set_left_child(BTnode_t* parent, BTnode_t* left_child) {
  if (parent)
    parent->left = left_child;
  if (left_child)
    left_child->parent = parent;
}

void set_right_child(BTnode_t* parent, BTnode_t* right_child) {
  if (parent)
    parent->right = right_child;
  if (right_child)
    right_child->parent = parent;
}

int is_root(BTnode_t* node) {
  return (node->parent == NULL);
}

int is_leaf(BTnode_t* node) {
  return (node->left == NULL && node->right == NULL);
}

int size(BTnode_t* root) {
  if (root==NULL)
    return 0;
  else // add +1 for the root
    return size(root->left) + size(root->right) + 1;
}

int max(int x, int y) {
  return x>y ? x : y;
}


int height(BTnode_t* root) {
  if (root == NULL)
    return -1;  // for consistency with leaf having height 1
  else if (is_leaf(root))
    return 0;
  else
    return max(height(root->left), height(root->right))+1;
}


int count_leaves(BTnode_t* root) {
  if (root == NULL)
    return 0;
  if (is_leaf(root))
    return 1;
  return count_leaves(root->left) + count_leaves(root->right);
}


int count_evens(BTnode_t* root) {
  if (root == NULL)
    return 0;
  if (root->value %2 == 0)
    return count_evens(root->left) + count_evens(root->right) + 1;
  else
    return count_evens(root->left) + count_evens(root->right);
}
  

void print_pre_order(BTnode_t* root) {
  if (root == NULL)
    return;

  printf("%d ", root->value);
  print_pre_order(root->left);
  print_pre_order(root->right);
}


void print_in_order(BTnode_t* root) {
  if (root == NULL)
    return;

  print_in_order(root->left);
  printf("%d ", root->value);
  print_in_order(root->right);
}


void print_post_order(BTnode_t* root) {
  if (root == NULL)
    return;

  print_post_order(root->left);
  print_post_order(root->right);
  printf("%d ", root->value);
}


LL_t* list_of_ancestors(BTnode_t* node) {
  LL_t* list = LLcreate();

  BTnode_t* current = node;
  while (current!=NULL) {
    LL_add_to_head(list, current); // add current vertex to the list
    current = current->parent; // go up in the tree
  }

  return list;
}



int BTdistance(BTnode_t* n1, BTnode_t* n2) {
  LL_t* l1 = list_of_ancestors(n1);
  LL_t* l2 = list_of_ancestors(n2);

  LLnode_t* ancestor1 = l1->head;
  LLnode_t* ancestor2 = l2->head;
  int common = 0;

  // compare the pointers to the ancestors nodes
  while (ancestor1==ancestor2) {
    common++;
    ancestor1 = ancestor1->next; // move forward in the linked list1
    ancestor2 = ancestor2->next; // move forward in the linked list2
  }
  printf("\n");
  
  int distance = LL_size(l1) + LL_size(l2) - 2*common;
  LL_free(l1);
  LL_free(l2);
  return distance;
}
