/*
 * node_list.c
 *
 *  Created on: Mar 8, 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 "list.h"
#include "node.h"
#include "node_list.h"

void node_list_destroy(node_list_t* list) {
	if(list != NULL) {
		list_destroy((list_t*) list);
	}
}

node_list_t* node_list_create() {
	node_list_t* list = (node_list_t*) malloc(sizeof(node_list_t));
	if(list == NULL) {
		return NULL;
	}
	memset(list, '\0', sizeof(node_list_t));

	// Initialize structure
	list_init((list_t*) list);
	list->count = 0;
	return list;
}

int node_list_add(node_list_t* list, node_t* node) {
	if (!list || !node) return -1;

	// Find the last element in the list
	node_t* last = list->end;

	// Setup our new node as the new last element
	node->next = NULL;
	node->prev = last;

	// Set the next element of our old "last" element
	if (last) {
		// but only if the node list is not empty
		last->next = node;
	}

	// Set the lists prev to the new last element
	list->end = node;

	// Increment our node count for this list
	list->count++;
	return 0;
}

int node_list_insert(node_list_t* list, unsigned int node_index, node_t* node) {
	if (!list || !node) return -1;
	if (node_index >= list->count) {
		return node_list_add(list, node);
	}

	// Get the first element in the list
	node_t* cur = list->begin;

	unsigned int pos = 0;
	node_t* prev = NULL;

	if (node_index > 0) {
		while (pos < node_index) {
			prev = cur;
			cur = cur->next;
			pos++;
		}
	}

	if (prev) {
		// Set previous node
		node->prev = prev;
		// Set next node of our new node to next node of the previous node
		node->next = prev->next;
		// Set next node of previous node to our new node
		prev->next = node;
	} else {
		node->prev = NULL;
		// get old first element in list
		node->next = list->begin;
		// set new node as first element in list
		list->begin = node;
	}

	if (node->next == NULL) {
		// Set the lists prev to the new last element
		list->end = node;
	} else {
		// set prev of the new next element to our node
		node->next->prev = node;
	}

	// Increment our node count for this list
	list->count++;
	return 0;
}

int node_list_remove(node_list_t* list, node_t* node) {
	if (!list || !node) return -1;
	if (list->count == 0) return -1;

	int node_index = 0;
	node_t* n;
	for (n = list->begin; n; n = n->next) {
		if (node == n) {
			node_t* newnode = node->next;
			if (node->prev) {
				node->prev->next = newnode;
				if (newnode) {
					newnode->prev = node->prev;
				} else {
					// last element in the list
					list->end = node->prev;
				}
			} else {
				// we just removed the first element
				if (newnode) {
					newnode->prev = NULL;
				}
				list->begin = newnode;
			}
			list->count--;
			return node_index;
		}
		node_index++;
	}	
	return -1;
}

