/***************************************************************************
 *   Copyright (C) 2005 by Nicolas Ternisien                               *
 *   nicolas.ternisien@gmail.com                                           *
 *                                                                         *
 *   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 "logLineList.h"
#include "logLine.h"

#include "view.h"


LogLineList::LogLineList() :
	oldestLogLine(NULL),
	firstAdd(true)
	{

}

LogLineList::~LogLineList() {

}

LogLine* LogLineList::getOldestLine() {
	return(oldestLogLine);
}

void LogLineList::removeOldestLine() {
	LogLine* line=this->getOldestLine();
	
	if (line!=NULL) {
		this->remove(line);
	}

}

bool LogLineList::isNewer(LogLine* line) {
	LogLine* olderLine=this->getOldestLine();
	
	if (olderLine==NULL)
		return(true);
		
	return(line->isNewerThan(*olderLine));

}

bool LogLineList::isEmpty() {
	return(list.isEmpty());
}


LogLine* LogLineList::lastLineInserted() {	
	//Can also returns NULL
	return(list.last());
}

int LogLineList::getNewLineCount() {
	return(addedList.count());
}

void LogLineList::insert(LogLine* line) {
	if (!isNewer(line) || list.count()==0) {
		oldestLogLine=line;
	}

	addedList.append(line);
	list.append(line);
}

bool LogLineList::lineAlreadyExists(LogLine* line) {
	TQPtrListIterator<LogLine> it(list);

	LogLine* other=it.current();
	while (other!=NULL) {
		if (other->equals(*line))
			return(true);
		
		++it;
		other=it.current();
	}

	return(false);
}


bool LogLineList::remove(LogLine* removedLine) {
	TQPtrListIterator<LogLine> it(list);

	LogLine* line=it.current();
	while (line!=NULL) {
		
		if (this->equals(removedLine, line)) {
			removedList.append(line);

			addedList.remove(line);
			list.remove(line);

			//Now find the new oldest line
			updateOldestLine();

			return(true);
		}
		
		++it;
		line=it.current();

	}

	return(false);
}

bool LogLineList::equals(LogLine* l1, LogLine* l2) {
	return(l1->equals(*l2));
}


int LogLineList::getItemCount() {
	return(list.count());
}

void LogLineList::clear() {
	TQPtrListIterator<LogLine> it(list);

	LogLine* line=it.current();
	while (line!=NULL) {
		removedList.append(line);
		
		++it;
		line=it.current();
	}
	
	list.clear();

	oldestLogLine=NULL;
}


LogLine* LogLineList::synchronize(View* view) {
	synchronizeRemovedLines(view);
	
	if (firstAdd==false && !addedList.isEmpty()) {
		synchronizeRecentLines();
	}

	LogLine* line=NULL;
	
	line=synchronizeAddedLines(view);
	
	kdDebug() << "Returning the added line..." << endl;
	
	return(line);
	
}

void LogLineList::synchronizeRemovedLines(View* view) {
	TQPtrListIterator<LogLine> it(removedList);
	
	LogLine* line=it.current();
	
	kdDebug() << "Removing old items from list..." << endl;
	
	//We removed the old items
	while(line!=NULL) {
		if (line->itemExists())
			line->removeItem(view->getLogList());
	
		//TODO Delete the line object
		
		++it;
		line=it.current();
	}
	
	removedList.clear();
	
}

LogLine* LogLineList::synchronizeAddedLines(View* view) {

	kdDebug() << "Adding new items to the list..." << endl;
	
	//We add the new items
	TQPtrListIterator<LogLine> it(addedList);
	
	LogLine* line=it.current();
	
	while (line!=NULL) {
		line->insertItem(view->getLogList());
		
		++it;
		line=it.current();
	}
	
	kdDebug() << "Returning latest item..." << endl;
	
	//Get the last line of addedList list (can be NULL)
	line=addedList.last();
	
	addedList.clear();

	//Returns line, even if line is NULL (must be tested by the caller class)
	return(line);
}

void LogLineList::synchronizeRecentLines() {
	kdDebug() << "Recent items become normal..." << endl;
	
	//The older lines are no longer recent
	TQPtrListIterator<LogLine> it(recentList);
	LogLine* line=it.current();
	
	while (line!=NULL) {
		//kdDebug() << "before setRecent... " << endl;
		//kdDebug() << "before setRecent original... : " << line->getOriginalFile() << endl;
		line->setRecent(false);
		//kdDebug() << "after setRecent..." << endl;
		
		++it;
		line=it.current();
	}
	recentList.clear();
	
	kdDebug() << "New items become recent..." << endl;
	
	//The new lines added becomes recent
	it=addedList;
	line=it.current();
	while (line!=NULL) {
		line->setRecent(true);
		recentList.append(line);
		
		++it;
		line=it.current();
	}
}

void LogLineList::setFirstReadPerformed(bool add) {
	firstAdd=!add;
}

void LogLineList::updateOldestLine() {
	
	TQPtrListIterator<LogLine> it(list);
	if (it.current()==NULL)
		oldestLogLine=NULL;
	
	oldestLogLine=it.current();
	
	LogLine* line=it.current();
	while (line!=NULL) {
		if (line->isOlderThan(*oldestLogLine))
			oldestLogLine=line;
			
		++it;
		line=it.current();
	}

}
