/*
 * 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_t* node) {
	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 index, node_t* node) {
	if (!list || !node) return -1;
	if (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 (index > 0) {
		while (pos < 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;

	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 0;
		}
	}	
	return -1;
}

