/*
 * node.c
 *
 *  Created on: Mar 7, 2011
 *      Author: posixninja
 *
 * Copyright (c) 2011 Joshua Hill. All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "node.h"
#include "node_list.h"

void node_destroy(node_t node)
{
	if(!node) return;

	if (node->children && node->children->count > 0) {
		node_t ch;
		while ((ch = node->children->begin)) {
			node_list_remove(node->children, ch);
			node_destroy(ch);
		}
	}
	node_list_destroy(node->children);
	node->children = NULL;

	free(node);
}

node_t node_create(node_t parent, void* data)
{
	int error = 0;

	node_t node = (node_t)calloc(1, sizeof(struct node));
	if (node == NULL) {
		return NULL;
	}

	node->data = data;
	node->next = NULL;
	node->prev = NULL;
	node->count = 0;
	node->parent = NULL;
	node->children = NULL;

	// Pass NULL to create a root node
	if(parent != NULL) {
		// This is a child node so attach it to it's parent
		error = node_attach(parent, node);
		if(error < 0) {
			// Unable to attach nodes
			printf("ERROR: %d \"Unable to attach nodes\"\n", error);
			node_destroy(node);
			return NULL;
		}
	}

	return node;
}

int node_attach(node_t parent, node_t child)
{
	if (!parent || !child) return -1;
	child->parent = parent;
	if(!parent->children) {
		parent->children = node_list_create();
	}
	int res = node_list_add(parent->children, child);
	if (res == 0) {
		parent->count++;
	}
	return res;
}

int node_detach(node_t parent, node_t child)
{
	if (!parent || !child) return -1;
	int node_index = node_list_remove(parent->children, child);
	if (node_index >= 0) {
		parent->count--;
	}
	return node_index;
}

int node_insert(node_t parent, unsigned int node_index, node_t child)
{
	if (!parent || !child) return -1;
	child->parent = parent;
	if(!parent->children) {
		parent->children = node_list_create();
	}
	int res = node_list_insert(parent->children, node_index, child);
	if (res == 0) {
		parent->count++;
	}
	return res;
}

static void _node_debug(node_t node, unsigned int depth)
{
	unsigned int i = 0;
	node_t current = NULL;
	for(i = 0; i < depth; i++) {
		printf("\t");
	}
	if(!node->parent) {
		printf("ROOT\n");
	}

	if(!node->children && node->parent) {
		printf("LEAF\n");
	} else {
		if(node->parent) {
			printf("NODE\n");
		}
		for (current = node_first_child(node); current; current = node_next_sibling(current)) {
			_node_debug(current, depth+1);
		}
	}

}

void node_debug(node_t node)
{
	_node_debug(node, 0);
}

unsigned int node_n_children(node_t node)
{
	if (!node) return 0;
	return node->count;
}

node_t node_nth_child(node_t node, unsigned int n)
{
	if (!node || !node->children || !node->children->begin) return NULL;
	unsigned int node_index = 0;
	int found = 0;
	node_t ch;
	for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
		if (node_index++ == n) {
			found = 1;
			break;
		}
	}
	if (!found) {
		return NULL;
	}
	return ch;
}

node_t node_first_child(node_t node)
{
	if (!node || !node->children) return NULL;
	return node->children->begin;
}

node_t node_prev_sibling(node_t node)
{
	if (!node) return NULL;
	return node->prev;
}

node_t node_next_sibling(node_t node)
{
	if (!node) return NULL;
	return node->next;
}

int node_child_position(node_t parent, node_t child)
{
	if (!parent || !parent->children || !parent->children->begin || !child) return -1;
	int node_index = 0;
	int found = 0;
	node_t ch;
	for (ch = node_first_child(parent); ch; ch = node_next_sibling(ch)) {
		if (ch == child) {
			found = 1;
			break;
		}
		node_index++;
	}
	if (!found) {
		return -1;
	}
	return node_index;
}

node_t node_copy_deep(node_t node, copy_func_t copy_func)
{
	if (!node) return NULL;
	void *data = NULL;
	if (copy_func) {
		data = copy_func(node->data);
	}
	node_t copy = node_create(NULL, data);
	node_t ch;
	for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
		node_t cc = node_copy_deep(ch, copy_func);
		node_attach(copy, cc);
	}
	return copy;
}
