/***************************************************************************
                          kfocuslog.cpp  -  description
                             -------------------
    begin                : Fri Aug 17 2001
    copyright            : (C) 2001 by Jeffrey Yu
    email                : wehjin@yahoo.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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "kfocuslogbook.h"
#include "kfocuslogentry.h"

KFMLogBook::KFMLogBook()
	: QObject()
{
	sorted_ = true;
	name_ = "Logname";
	currentEntry_ = NULL;
	entryList_ = new QSortedList<KFMLog>;
		entryList_->setAutoDelete(true);
}

KFMLogBook::~KFMLogBook()
{
	delete entryList_;
}


/** XML tag for this object */
QString KFMLogBook::xmlTag(){
	return QString("logbook");
}

/** Form a DOM element from the logBook */
QDomElement KFMLogBook::domElement(QDomDocument* dDoc){
	QDomElement eLog = dDoc->createElement(xmlTag());
		QDomElement eName = dDoc->createElement("name");
			eName.appendChild(dDoc->createTextNode(name()));
			eLog.appendChild(eName);
		
		currentEntry(firstEntry());
		while (currentEntry() != NULL) {
			eLog.appendChild(currentEntry()->domElement(dDoc));
		
			currentEntry(nextEntry());
		}
		
		return eLog;
}

/** Setup a logBook from a DOM element */
void KFMLogBook::domElement(QDomElement eLog){
	sorted(false);
	
	QDomNode n = eLog.firstChild();
	while (!n.isNull()) {
		QDomElement e = n.toElement();
		if (!e.isNull()) {
			if (e.tagName() == "name") {
				QDomText t = e.firstChild().toText();
				name(t.data());
			}
			else if (e.tagName() == "entry") {
				KFMLog* entry = new KFMLog();
				entry->domElement(e);
				addEntry(entry);
			}
		}
	
		n = n.nextSibling();
	}
	
	sorted(true);
}


/** Toggle sorting on and off */
void KFMLogBook::sorted(bool sorted){
	if (sorted != sorted_) {
		sorted_ = sorted;	
		if (sorted_)
			sort();	
	}
}


/** Get the name of the logBook */
QString KFMLogBook::name() const{
	return name_;
}

/** Set the name of the logBook */
void KFMLogBook::name(QString name){
	name_ = name;
	
	nameChanged(name);
	contentsChanged();
}


/** See how many entries are in the logBook */
int KFMLogBook::numEntries() const{
	return entryList_->count();
}

/** Query if an entry is in the logBook */
bool KFMLogBook::isEntry(KFMLog* entry) const{
	return (entryList_->findRef(entry) >= 0);
}

/** Add an entry to the logBook */
void KFMLogBook::addEntry(KFMLog* entry){
	if (entry == NULL) return;
	
	if (!isEntry(entry)) {
			// Add it to the entries list and sort it
			entryList_->append(entry);
			sort();

			// Connect to the entry				
			connect(entry, SIGNAL( contentsChanged() ), this, SLOT( onEntryContentsChanged() ));
			connect(entry, SIGNAL( dateChanged(KFMLog*) ), this,
				SLOT( onEntryDateChanged(KFMLog*) ));
			
			// Make it the current entry
			currentEntry(entry);
			
			
			emit entryAdded(entry);
			emit contentsChanged();
	}
}

/** Remove an entry from the logBook */
void KFMLogBook::removeEntry(KFMLog* entry){
	if (isEntry(entry)) {
		// Make sure it isn't the current entry
		if (currentEntry() == entry)
			currentEntry(NULL);
		
		// Disconnect from the entry
		disconnect(entry, 0, this, 0);
		
		// Remove it from the entries list
		int pos = entryList_->findRef(entry);
		entryList_->remove(entry);
		
		emit entryRemoved(entry, pos);		
		emit contentsChanged();
	}
}

/** Remove all entries from the list */
void KFMLogBook::clearEntries(){
	if (firstEntry() != NULL) {
		currentEntry(NULL);
		
		entryList_->clear();
	
		entryRemoved(NULL, 0);
		contentsChanged();
	}
}


/** Change the date of an entry */
void KFMLogBook::redateEntry(KFMLog* entry, QDate date){	
	if (isEntry(entry)) {
		entry->date(date);
	}
}


/** Retrieve the current entry */
KFMLog* KFMLogBook::currentEntry() const{
	return currentEntry_;
}

/** Change the current entry */
void KFMLogBook::currentEntry(KFMLog* entry){
	if (isEntry(entry)) {
		currentEntry_ = entry;
	}
	else
		currentEntry_ = NULL;
}


/** Retrieve the position of the current entry */
int KFMLogBook::currentPosition() const {
	return entryList_->findRef(currentEntry());
}

/** Make the entry at pos the current entry */
void KFMLogBook::currentPosition(int pos){
	currentEntry(entryList_->at(pos));
}


/** No descriptions */
KFMLog* KFMLogBook::firstEntry() const{
	return entryList_->getFirst();
}

/** Get the next entry in the logBook (after the current entry) */
KFMLog* KFMLogBook::nextEntry() const{
	entryList_->findRef(currentEntry());
	return entryList_->next();
}

/** Retrieve the last entry in the logBook */
KFMLog* KFMLogBook::lastEntry() const{
	return entryList_->getLast();
}



//////////////////////////////////////////////////////////
// Private methods

/** Sort the logs in the logbook. */
void KFMLogBook::sort(){
	if (sorted_) {
		setLogPositions();
		
		entryList_->sort();		
	}
}


/** Set the position fields of logs in the logbook.  This is normally
		called before sorting the logbook to preserve the relative order of logs
		that are equal. */
void KFMLogBook::setLogPositions(){
	// label tasks with their linear positions
	Iterator it = logIterator();
	int i = 0;
	for (;it.current();++it,++i) {
		it.current()->position(i);
	}
}


/** Private slot for when a logentry is changed */
void KFMLogBook::onEntryContentsChanged(){
	contentsChanged();
}


/** Slot to receive dateChanged signal from an entry */
void KFMLogBook::onEntryDateChanged(KFMLog* entry){
	if (isEntry(entry)) {
		// Remove the entry, but set autodelete false so we don't lose it
		entryList_->setAutoDelete(false);
		removeEntry(entry);
		entryList_->setAutoDelete(true);
		
		// Reinsert it
		addEntry(entry);	
	}
}
