/******************************************************************************
Copyright (C) 2005 Matteo Lucarelli

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
******************************************************************************/

#include "dynaList.h"

dynaList::dynaList(int count)
{
	m_first=NULL;
	m_last=NULL;
	for (int i=0; i<count; i++) addNewFirst();//addNewLast();
	m_current=m_first;
}

dynaList::~dynaList()
{
	delAll();
}

bool dynaList::addNewLast(void *payload)
{
	listItem *tmp=new listItem;
	if (!tmp) return false;
	tmp->payload=payload;
	tmp->next=NULL;
	tmp->prev=m_last;
	if (m_last) m_last->next=tmp;
	m_last=tmp;
	m_current=m_last;
	if (!m_first) m_first=m_last;
	return true;
}

bool dynaList::addNewFirst(void *payload)
{
	listItem *tmp=new listItem;
	if (!tmp) return false;
	tmp->payload=payload;
	tmp->prev=NULL;
	tmp->next=m_first;
	if (m_first) m_first->prev=tmp;
	m_first=tmp;
	m_current=m_first;
	if (!m_last) m_last=m_first;
	return true;
}

bool dynaList::addNewBeforeCurrent(void *payload)
{
	if (!m_current) return false;
	if (m_current==m_first) return addNewFirst(payload);
	listItem *tmp=new listItem;
	if (!tmp) return false;
	tmp->payload=payload;
	tmp->next=m_current;
	tmp->prev=m_current->prev;
	m_current->prev=tmp;
	tmp->prev->next=tmp;
	m_current=tmp;
	return true;
}

bool dynaList::addNewAfterCurrent(void *payload)
{
	if (!m_current) return false;
	if (m_current==m_last) return addNewLast(payload);
	listItem *tmp=new listItem;
	if (!tmp) return false;
	tmp->payload=payload;
	tmp->prev=m_current;
	tmp->next=m_current->next;
	m_current->next=tmp;
	tmp->next->prev=tmp;
	m_current=tmp;
	return false;
}

void dynaList::delAll()
{
	m_current=m_last;
	while (m_current) delLast();
}

void *dynaList::delFirst()
{
	void *ret=NULL;
	if (m_first){
		ret=m_first->payload;
		listItem *tmp=m_first->next;
		if (m_current==m_first) m_current=tmp;
		delete m_first;
		if (tmp) tmp->prev=NULL;
		else m_last=NULL;
		m_first=tmp;
	}
	return ret;
}


void *dynaList::delLast()
{
	void *ret=NULL;
	if (m_last){
		ret=m_last->payload;
		listItem *tmp=m_last->prev;
		if (m_current==m_last) m_current=tmp;
		delete m_last;
		if (tmp) tmp->next=NULL;
		else m_first=NULL;
		m_last=tmp;
	}
	return ret;
}

void *dynaList::delCurrent()
{
	if (m_current==m_first) return (delFirst());
	if (m_current==m_last) return (delLast());
	
	void *ret=m_current->payload;
	m_current->next->prev=m_current->prev;
	m_current->prev->next=m_current->next;
	delete m_current;
	m_current=m_first;
	return ret;
}

bool dynaList::moveFirst()
{
	m_current=m_first;
	return (m_current!=NULL);
}

bool dynaList::moveNext()
{
	if (m_current==m_last) return false;
	m_current=m_current->next;
	return true;
}

bool dynaList::movePrev()
{
	if (m_current==m_first) return false;
	m_current=m_current->prev;	
	return true;
}

bool dynaList::moveTo(int index)
{
	int i;
	m_current=m_first;
	for (i=1;i<index;i++) if(!moveNext()) break;
	return (i==index);
}

bool dynaList::moveLast()
{
	m_current=m_last;
	return (m_current!=NULL);
}

bool dynaList::setCurrentPayload(void *obj)
{
	if (!m_current) return false;
	m_current->payload=obj;
	return true;
}

void *dynaList::getCurrentPayload()
{
	if (!m_current) return NULL;
	return (m_current->payload);
}

int dynaList::getCurrentIndex()
{
	if (!m_current) return 0;
	int ret=1;
	listItem *tmp=m_current;
	while (tmp=tmp->prev) ret++;
	return ret;
}

int dynaList::getCount()
{
	if (!m_first) return 0;
	int ret=1;
	listItem *tmp=m_first;
	while (tmp=tmp->next) ret++;
	return ret;
}