/*
    historylogger.cpp

    Copyright (c) 2003-2004 by Olivier Goffart        <ogoffart @ kde.org>

    Kopete    (c) 2003-2004 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * 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 "historylogger.h"
#include "historyconfig.h"

#include <tqregexp.h>
#include <tqfile.h>
#include <tqdir.h>
#include <tqdatetime.h>
#include <tqdom.h>
#include <tqtimer.h>

#include <kdebug.h>
#include <tdestandarddirs.h>
#include <ksavefile.h>

#include "kopeteglobal.h"
#include "kopetecontact.h"
#include "kopeteprotocol.h"
#include "kopeteaccount.h"
#include "kopetemetacontact.h"
#include "kopetechatsession.h"

// -----------------------------------------------------------------------------
HistoryLogger::HistoryLogger( Kopete::MetaContact *m,  TQObject *parent, const char *name )
 : TQObject(parent, name)
{
	m_saveTimer=0L;
	m_saveTimerTime=0;
	m_metaContact=m;
	m_hideOutgoing=false;
	m_cachedMonth=-1;
	m_realMonth=TQDate::currentDate().month();
	m_oldSens=Default;

	//the contact may be destroyed, for example, if the contact changes its metacontact
	connect(m_metaContact , TQ_SIGNAL(destroyed(TQObject *)) , this , TQ_SLOT(slotMCDeleted()));

	setPositionToLast();
}


HistoryLogger::HistoryLogger( Kopete::Contact *c,  TQObject *parent, const char *name )
 : TQObject(parent, name)
{
	m_saveTimer=0L;
	m_saveTimerTime=0;
	m_cachedMonth=-1;
	m_metaContact=c->metaContact();
	m_hideOutgoing=false;
	m_realMonth=TQDate::currentDate().month();
	m_oldSens=Default;

	//the contact may be destroyed, for example, if the contact changes its metacontact
	connect(m_metaContact , TQ_SIGNAL(destroyed(TQObject *)) , this , TQ_SLOT(slotMCDeleted()));

	setPositionToLast();
}


HistoryLogger::~HistoryLogger()
{
	if(m_saveTimer && m_saveTimer->isActive())
		saveToDisk();
}


void HistoryLogger::setPositionToLast()
{
	setCurrentMonth(0);
	m_oldSens = AntiChronological;
	m_oldMonth=0;
	m_oldElements.clear();
}


void HistoryLogger::setPositionToFirst()
{
	setCurrentMonth( getFirstMonth() );
	m_oldSens = Chronological;
	m_oldMonth=m_currentMonth;
	m_oldElements.clear();
}


void HistoryLogger::setCurrentMonth(int month)
{
	m_currentMonth = month;
	m_currentElements.clear();
}


TQDomDocument HistoryLogger::getDocument(const Kopete::Contact *c, unsigned int month , bool canLoad , bool* contain)
{
	if(m_realMonth!=TQDate::currentDate().month())
	{ //We changed month, our indice are not correct anymore, clean memory.
	  // or we will see what i called "the 31 midnight bug"(TM) :-)  -Olivier
		m_documents.clear();
		m_cachedMonth=-1;
		m_currentMonth++; //Not usre it's ok, but should work;
		m_oldMonth++;     // idem
		m_realMonth=TQDate::currentDate().month();
	}

	if(!m_metaContact)
	{ //this may happen if the contact has been moved, and the MC deleted
		if(c && c->metaContact())
			m_metaContact=c->metaContact();
		else
			return TQDomDocument();
	}

	if(!m_metaContact->contacts().contains(c))
	{
		if(contain)
			*contain=false;
		return TQDomDocument();
	}

	TQMap<unsigned int , TQDomDocument> documents = m_documents[c];
	if (documents.contains(month))
		return documents[month];


	TQDomDocument doc =  getDocument(c, TQDate::currentDate().addMonths(0-month), canLoad, contain);

	documents.insert(month, doc);
	m_documents[c]=documents;

	return doc;

}

TQDomDocument HistoryLogger::getDocument(const Kopete::Contact *c, const TQDate date , bool canLoad , bool* contain)
{
	if(!m_metaContact)
	{ //this may happen if the contact has been moved, and the MC deleted
		if(c && c->metaContact())
			m_metaContact=c->metaContact();
		else
			return TQDomDocument();
	}

	if(!m_metaContact->contacts().contains(c))
	{
		if(contain)
			*contain=false;
		return TQDomDocument();
	}

	if(!canLoad)
	{
		if(contain)
			*contain=false;
		return TQDomDocument();
	}

	TQString	FileName = getFileName(c, date);

	TQDomDocument doc( "Kopete-History" );

	TQFile file( FileName );
	if ( !file.open( IO_ReadOnly ) )
	{
		if(contain)
			*contain=false;
		return doc;
	}
	if ( !doc.setContent( &file ) )
	{
		file.close();
		if(contain)
			*contain=false;
		return doc;
	}
	file.close();

	if(contain)
		*contain=true;

	return doc;
}


void HistoryLogger::appendMessage( const Kopete::Message &msg , const Kopete::Contact *ct )
{
	if(!msg.from())
		return;

	// If no contact are given: If the manager is availiable, use the manager's
	// first contact (the channel on irc, or the other contact for others protocols
	const Kopete::Contact *c = ct;
	if(!c && msg.manager() )
	{
		TQPtrList<Kopete::Contact> mb=msg.manager()->members() ;
		c = mb.first();
	}
	if(!c)  //If the contact is still not initialized, use the message author.
		c =   msg.direction()==Kopete::Message::Outbound ? msg.to().first() : msg.from()  ;


	if(!m_metaContact)
	{ //this may happen if the contact has been moved, and the MC deleted
		if(c && c->metaContact())
			m_metaContact=c->metaContact();
		else
			return;
	}


	if(!c || !m_metaContact->contacts().contains(c) )
	{
		/*TQPtrList<Kopete::Contact> contacts= m_metaContact->contacts();
		TQPtrListIterator<Kopete::Contact> it( contacts );
		for( ; it.current(); ++it )
		{
			if( (*it)->protocol()->pluginId() == msg.from()->protocol()->pluginId() )
			{
				c=*it;
				break;
			}
		}*/
		//if(!c)

		kdWarning(14310) << k_funcinfo << "No contact found in this metacontact to" <<
			" append in the history" << endl;
		return;
	}

	TQDomDocument doc=getDocument(c,0);
	TQDomElement docElem = doc.documentElement();

	if(docElem.isNull())
	{
		docElem= doc.createElement( "kopete-history" );
		docElem.setAttribute ( "version" , "0.9" );
		doc.appendChild( docElem );
		TQDomElement headElem = doc.createElement( "head" );
		docElem.appendChild( headElem );
		TQDomElement dateElem = doc.createElement( "date" );
		dateElem.setAttribute( "year",  TQString::number(TQDate::currentDate().year()) );
		dateElem.setAttribute( "month", TQString::number(TQDate::currentDate().month()) );
		headElem.appendChild(dateElem);
		TQDomElement myselfElem = doc.createElement( "contact" );
		myselfElem.setAttribute( "type",  "myself" );
		myselfElem.setAttribute( "contactId", c->account()->myself()->contactId() );
		headElem.appendChild(myselfElem);
		TQDomElement contactElem = doc.createElement( "contact" );
		contactElem.setAttribute( "contactId", c->contactId() );
		headElem.appendChild(contactElem);
	}

	TQDomElement msgElem = doc.createElement( "msg" );
	msgElem.setAttribute( "in",  msg.direction()==Kopete::Message::Outbound ? "0" : "1" );
	msgElem.setAttribute( "from",  msg.from()->contactId() );
	msgElem.setAttribute( "nick",  msg.from()->property( Kopete::Global::Properties::self()->nickName() ).value().toString() ); //do we have to set this?
	msgElem.setAttribute( "time", msg.timestamp().toString("d h:m:s") );

	TQDomText msgNode = doc.createTextNode( msg.plainBody() );
	docElem.appendChild( msgElem );
	msgElem.appendChild( msgNode );


	// I'm temporizing the save.
	// On hight-traffic channel, saving can take lots of CPU. (because the file is big)
	// So i wait a time proportional to the time needed to save..

	const TQString filename=getFileName(c,TQDate::currentDate());
	if(!m_toSaveFileName.isEmpty() && m_toSaveFileName != filename)
	{ //that mean the contact or the month has changed, save it now.
		saveToDisk();
	}

	m_toSaveFileName=filename;
	m_toSaveDocument=doc;

	if(!m_saveTimer)
	{
		m_saveTimer=new TQTimer(this);
		connect( m_saveTimer, TQ_SIGNAL( timeout() ) , this, TQ_SLOT(saveToDisk()) );
	}
	if(!m_saveTimer->isActive())
		m_saveTimer->start( m_saveTimerTime, true /*singleshot*/ );
}

void HistoryLogger::saveToDisk()
{
	if(m_saveTimer)
		m_saveTimer->stop();
	if(m_toSaveFileName.isEmpty() || m_toSaveDocument.isNull())
		return;

	TQTime t;
	t.start(); //mesure the time needed to save.

	KSaveFile file( m_toSaveFileName );
	if( file.status() == 0 )
	{
		TQTextStream *stream = file.textStream();
		//stream->setEncoding( TQTextStream::UnicodeUTF8 ); //???? oui ou non?
		m_toSaveDocument.save( *stream, 1 );
		file.close();

		m_saveTimerTime=TQMIN(t.elapsed()*1000, 300000);
		    //a time 1000 times supperior to the time needed to save.  but with a upper limit of 5 minutes
		//on a my machine, (2.4Ghz, but old HD) it should take about 10 ms to save the file.
		// So that would mean save every 10 seconds, which seems to be ok.
		// But it may take 500 ms if the file to save becomes too big (1Mb).
		kdDebug(14310) << k_funcinfo << m_toSaveFileName << " saved in " << t.elapsed() << " ms " <<endl ;

		m_toSaveFileName=TQString();
		m_toSaveDocument=TQDomDocument();
	}
	else
		kdError(14310) << k_funcinfo << "impossible to save the history file " << m_toSaveFileName << endl;

}

TQValueList<Kopete::Message> HistoryLogger::readMessages(TQDate date)
{
	TQRegExp rxTime("(\\d+) (\\d+):(\\d+)($|:)(\\d*)"); //(with a 0.7.x compatibility)
	TQValueList<Kopete::Message> messages;


	TQPtrList<Kopete::Contact> ct=m_metaContact->contacts();
	TQPtrListIterator<Kopete::Contact> it( ct );

	for( ; it.current(); ++it )
	{
		TQDomDocument doc=getDocument(*it,date, true, 0L);
		TQDomElement docElem = doc.documentElement();
		TQDomNode n = docElem.firstChild();

		while(!n.isNull())
		{
			TQDomElement  msgElem2 = n.toElement();
			if( !msgElem2.isNull() && msgElem2.tagName()=="msg")
			{
				rxTime.search(msgElem2.attribute("time"));
				TQDateTime dt( TQDate(date.year() , date.month() , rxTime.cap(1).toUInt()), TQTime( rxTime.cap(2).toUInt() , rxTime.cap(3).toUInt(), rxTime.cap(5).toUInt()  ) );

				if (dt.date() != date)
				{
					n = n.nextSibling();
					continue;
				}

				Kopete::Message::MessageDirection dir = (msgElem2.attribute("in") == "1") ?
						Kopete::Message::Inbound : Kopete::Message::Outbound;

				if(!m_hideOutgoing || dir != Kopete::Message::Outbound)
				{ //parse only if we don't hide it

					TQString f=msgElem2.attribute("from" );
					const Kopete::Contact *from=f.isNull()? 0L : (*it)->account()->contacts()[f];

					if(!from)
						from= dir==Kopete::Message::Inbound ? (*it) : (*it)->account()->myself();

					Kopete::ContactPtrList to;
					to.append( dir==Kopete::Message::Inbound ? (*it)->account()->myself() : *it );

					Kopete::Message msg(dt, from, to, msgElem2.text(), dir);
					msg.setBody( TQString::fromLatin1("<span title=\"%1\">%2</span>")
							.arg( dt.toString(TQt::LocalDate), msg.escapedBody() ),
							Kopete::Message::RichText);
				

					// We insert it at the good place, given its date
 					TQValueListIterator<Kopete::Message> msgIt;
					
					for (msgIt = messages.begin(); msgIt != messages.end(); ++msgIt)
					{
						if ((*msgIt).timestamp() > msg.timestamp())
							break;
					}
					messages.insert(msgIt, msg);
				}
			}

			n = n.nextSibling();
		} // end while on messages
		
	}
	return messages;
}

TQValueList<Kopete::Message> HistoryLogger::readMessages(unsigned int lines,
	const Kopete::Contact *c, Sens sens, bool reverseOrder, bool colorize)
{
	//TQDate dd =  TQDate::currentDate().addMonths(0-m_currentMonth);

	TQValueList<Kopete::Message> messages;

	// A regexp useful for this function
	TQRegExp rxTime("(\\d+) (\\d+):(\\d+)($|:)(\\d*)"); //(with a 0.7.x compatibility)

	if(!m_metaContact)
	{ //this may happen if the contact has been moved, and the MC deleted
		if(c && c->metaContact())
			m_metaContact=c->metaContact();
		else
			return messages;
	}

	if(c && !m_metaContact->contacts().contains(c) )
		return messages;

	if(sens ==0 )  //if no sens are selected, just continue in the previous sens
		sens = m_oldSens ;
	if( m_oldSens != 0 && sens != m_oldSens )
	{ //we changed our sens! so retrieve the old position to fly in the other way
		m_currentElements= m_oldElements;
		m_currentMonth=m_oldMonth;
	}
	else
	{
		m_oldElements=m_currentElements;
		m_oldMonth=m_currentMonth;
	}
	m_oldSens=sens;

	//getting the color for messages:
	TQColor fgColor = HistoryConfig::history_color();

	//Hello guest!

	//there are two algoritms:
	// - if a contact is given, or the metacontact contain only one contact,  just read the history.
	// - else, merge the history

	//the merging algoritm is the following:
	// we see what contact we have to read first, and we look at the firt date before another contact
	// has a message with a bigger date.

	TQDateTime timeLimit;
	const Kopete::Contact *currentContact=c;
	if(!c && m_metaContact->contacts().count()==1)
		currentContact=m_metaContact->contacts().first();
	else if(!c && m_metaContact->contacts().count()== 0)
	{
		return messages;
	}
	
	while(messages.count() < lines)
	{
		timeLimit=TQDateTime();
		TQDomElement msgElem; //here is the message element
		TQDateTime timestamp; //and the timestamp of this message

		if(!c && m_metaContact->contacts().count()>1)
		{ //we have to merge the differents subcontact history
			TQPtrList<Kopete::Contact> ct=m_metaContact->contacts();
			TQPtrListIterator<Kopete::Contact> it( ct );
			for( ; it.current(); ++it )
			{ //we loop over each contact. we are searching the contact with the next message with the smallest date,
			  // it will becomes our current contact, and the contact with the mext message with the second smallest
			  // date, this date will bocomes the limit.

				TQDomNode n;
				if(m_currentElements.contains(*it))
					n=m_currentElements[*it];
				else  //there is not yet "next message" register, so we will take the first  (for the current month)
				{
					TQDomDocument doc=getDocument(*it,m_currentMonth);
					TQDomElement docElem = doc.documentElement();
					n= (sens==Chronological)?docElem.firstChild() : docElem.lastChild();

					//i can't drop the root element
					workaround.append(docElem);
				}
				while(!n.isNull())
				{
					TQDomElement  msgElem2 = n.toElement();
					if( !msgElem2.isNull() && msgElem2.tagName()=="msg")
					{
						rxTime.search(msgElem2.attribute("time"));
						TQDate d=TQDate::currentDate().addMonths(0-m_currentMonth);
						TQDateTime dt( TQDate(d.year() , d.month() , rxTime.cap(1).toUInt()), TQTime( rxTime.cap(2).toUInt() , rxTime.cap(3).toUInt(), rxTime.cap(5).toUInt()  ) );
						if(!timestamp.isValid() || ((sens==Chronological )? dt < timestamp : dt > timestamp) )
						{
							timeLimit=timestamp;
							timestamp=dt;
							msgElem=msgElem2;
							currentContact=*it;

						}
						else if(!timeLimit.isValid() || ((sens==Chronological) ? timeLimit > dt : timeLimit < dt) )
						{
							timeLimit=dt;
						}
						break;
					}
					n=(sens==Chronological)? n.nextSibling() : n.previousSibling();
				}
			}
		}
		else  //we don't have to merge the history. just take the next item in the contact
		{
			if(m_currentElements.contains(currentContact))
				msgElem=m_currentElements[currentContact];
			else
			{
				TQDomDocument doc=getDocument(currentContact,m_currentMonth);
				TQDomElement docElem = doc.documentElement();
				TQDomNode n= (sens==Chronological)?docElem.firstChild() : docElem.lastChild();
				msgElem=TQDomElement();
				while(!n.isNull()) //continue until we get a msg
				{
					msgElem=n.toElement();
					if( !msgElem.isNull() && msgElem.tagName()=="msg")
					{
						m_currentElements[currentContact]=msgElem;
						break;
					}
					n=(sens==Chronological)? n.nextSibling() : n.previousSibling();
				}

				//i can't drop the root element
				workaround.append(docElem);
			}
		}


		if(msgElem.isNull()) //we don't find ANY messages in any contact for this month. so we change the month
		{
			if(sens==Chronological)
			{
				if(m_currentMonth <= 0)
					break; //there are no other messages to show. break even if we don't have nb messages
				setCurrentMonth(m_currentMonth-1);
			}
			else
			{
				if(m_currentMonth >= getFirstMonth(c))
					break; //we don't have any other messages to show
				setCurrentMonth(m_currentMonth+1);
			}
			continue; //begin the loop from the bottom, and find currentContact and timeLimit again
		}

		while(
			(messages.count() < lines) &&
			!msgElem.isNull() &&
			(!timestamp.isValid() || !timeLimit.isValid() ||
				((sens==Chronological) ? timestamp <= timeLimit : timestamp >= timeLimit)
			))
		{
			// break this loop, if we have reached the correct number of messages,
			// if there are no more messages for this contact, or if we reached
			// the timeLimit msgElem is the next message, still not parsed, so
			// we parse it now

			Kopete::Message::MessageDirection dir = (msgElem.attribute("in") == "1") ?
				Kopete::Message::Inbound : Kopete::Message::Outbound;

			if(!m_hideOutgoing || dir != Kopete::Message::Outbound)
			{ //parse only if we don't hide it

				if( m_filter.isNull() || ( m_filterRegExp? msgElem.text().contains(TQRegExp(m_filter,m_filterCaseSensitive)) : msgElem.text().contains(m_filter,m_filterCaseSensitive) ))
				{
					TQString f=msgElem.attribute("from" );
					const Kopete::Contact *from=(f.isNull() || !currentContact) ? 0L : currentContact->account()->contacts()[f];

					if(!from)
						from= dir==Kopete::Message::Inbound ? currentContact : currentContact->account()->myself();

					Kopete::ContactPtrList to;
					to.append( dir==Kopete::Message::Inbound ? currentContact->account()->myself() : currentContact );

					if(!timestamp.isValid())
					{
						//parse timestamp only if it was not already parsed
						rxTime.search(msgElem.attribute("time"));
						TQDate d=TQDate::currentDate().addMonths(0-m_currentMonth);
						timestamp=TQDateTime( TQDate(d.year() , d.month() , rxTime.cap(1).toUInt()), TQTime( rxTime.cap(2).toUInt() , rxTime.cap(3).toUInt() , rxTime.cap(5).toUInt() ) );
					}

					Kopete::Message msg(timestamp, from, to, msgElem.text(), dir);
					if (colorize)
					{
						msg.setBody( TQString::fromLatin1("<span style=\"color:%1\" title=\"%2\">%3</span>")
							.arg( fgColor.name(), timestamp.toString(TQt::LocalDate), msg.escapedBody() ),
							Kopete::Message::RichText
						);
						msg.setFg( fgColor );
					}
					else
					{
						msg.setBody( TQString::fromLatin1("<span title=\"%1\">%2</span>")
							.arg( timestamp.toString(TQt::LocalDate), msg.escapedBody() ),
							Kopete::Message::RichText
						);
					}

					if(reverseOrder)
						messages.prepend(msg);
					else
						messages.append(msg);
				}
			}

			//here is the point of workaround. If i drop the root element, this crashes
			//get the next message
			TQDomNode node = ( (sens==Chronological) ? msgElem.nextSibling() :
				msgElem.previousSibling() );

			msgElem = TQDomElement(); //n.toElement();
			while (!node.isNull() && msgElem.isNull())
			{
				msgElem = node.toElement();
				if (!msgElem.isNull())
				{
					if (msgElem.tagName() == "msg")
					{
						if (!c && (m_metaContact->contacts().count() > 1))
						{
							// In case of hideoutgoing messages, it is faster to do
							// this, so we don't parse the date if it is not needed
							TQRegExp rx("(\\d+) (\\d+):(\\d+):(\\d+)");
							rx.search(msgElem.attribute("time"));

							TQDate d = TQDate::currentDate().addMonths(0-m_currentMonth);
							timestamp = TQDateTime(
								TQDate(d.year(), d.month(), rx.cap(1).toUInt()),
								TQTime( rx.cap(2).toUInt(), rx.cap(3).toUInt() ) );
						}
						else
							timestamp = TQDateTime(); //invalid
					}
					else
						msgElem = TQDomElement();
				}

				node = (sens == Chronological) ? node.nextSibling() :
					node.previousSibling();
			}
			m_currentElements[currentContact]=msgElem;  //this is the next message
		}
	}

	if(messages.count() < lines)
		m_currentElements.clear(); //current elements are null this can't be allowed

	return messages;
}

TQString HistoryLogger::getFileName(const Kopete::Contact* c, TQDate date)
{
	
	TQString name = c->protocol()->pluginId().replace( TQRegExp( TQString::fromLatin1( "[./~?*]" ) ), TQString::fromLatin1( "-" ) ) +
		TQString::fromLatin1( "/" ) +
		c->account()->accountId().replace( TQRegExp( TQString::fromLatin1( "[./~?*]" ) ), TQString::fromLatin1( "-" ) ) +
		TQString::fromLatin1( "/" ) +
	c->contactId().replace( TQRegExp( TQString::fromLatin1( "[./~?*]" ) ), TQString::fromLatin1( "-" ) ) +
		date.toString(".yyyyMM");

	TQString filename=locateLocal( "data", TQString::fromLatin1( "kopete/logs/" ) + name+ TQString::fromLatin1( ".xml" ) ) ;

	//Check if there is a kopete 0.7.x file
	TQFileInfo fi(filename);
	if(!fi.exists())
	{
		name = c->protocol()->pluginId().replace( TQRegExp( TQString::fromLatin1( "[./~?*]" ) ), TQString::fromLatin1( "-" ) ) +
			TQString::fromLatin1( "/" ) +
			c->contactId().replace( TQRegExp( TQString::fromLatin1( "[./~?*]" ) ), TQString::fromLatin1( "-" ) ) +
			date.toString(".yyyyMM");

		TQString filename2=locateLocal( "data", TQString::fromLatin1( "kopete/logs/" ) + name+ TQString::fromLatin1( ".xml" ) ) ;

		TQFileInfo fi2(filename2);
		if(fi2.exists())
			return filename2;
	}

	return filename;

}

unsigned int HistoryLogger::getFirstMonth(const Kopete::Contact *c)
{
	if(!c)
		return getFirstMonth();

	TQRegExp rx( "\\.(\\d\\d\\d\\d)(\\d\\d)" );
	TQFileInfo *fi;

	// BEGIN check if there are Kopete 0.7.x
	TQDir d1(locateLocal("data",TQString("kopete/logs/")+
		c->protocol()->pluginId().replace( TQRegExp(TQString::fromLatin1("[./~?*]")),TQString::fromLatin1("-"))
		));
	d1.setFilter( TQDir::Files | TQDir::NoSymLinks );
	d1.setSorting( TQDir::Name );

	const TQFileInfoList *list1 = d1.entryInfoList();
	TQFileInfoListIterator it1( *list1 );

	while ( (fi = it1.current()) != 0 )
	{
		if(fi->fileName().contains(c->contactId().replace( TQRegExp( TQString::fromLatin1( "[./~?*]" ) ), TQString::fromLatin1( "-" ) )))
		{
			rx.search(fi->fileName());
			int result = 12*(TQDate::currentDate().year() - rx.cap(1).toUInt()) +TQDate::currentDate().month() - rx.cap(2).toUInt();

			if(result < 0)
			{
				kdWarning(14310) << k_funcinfo << "Kopete only found log file from Kopete 0.7.x made in the future. Check your date!" << endl;
				break;
			}
			return result;
		}
		++it1;
	}
	// END of kopete 0.7.x check


	TQDir d(locateLocal("data",TQString("kopete/logs/")+
		c->protocol()->pluginId().replace( TQRegExp(TQString::fromLatin1("[./~?*]")),TQString::fromLatin1("-")) +
		TQString::fromLatin1( "/" ) +
		c->account()->accountId().replace( TQRegExp( TQString::fromLatin1( "[./~?*]" ) ), TQString::fromLatin1( "-" ) )
		));

	d.setFilter( TQDir::Files | TQDir::NoSymLinks );
	d.setSorting( TQDir::Name );

	const TQFileInfoList *list = d.entryInfoList();
	TQFileInfoListIterator it( *list );
	while ( (fi = it.current()) != 0 )
	{
		if(fi->fileName().contains(c->contactId().replace( TQRegExp( TQString::fromLatin1( "[./~?*]" ) ), TQString::fromLatin1( "-" ) )))
		{
			rx.search(fi->fileName());
			int result = 12*(TQDate::currentDate().year() - rx.cap(1).toUInt()) +TQDate::currentDate().month() - rx.cap(2).toUInt();
			if(result < 0)
			{
				kdWarning(14310) << k_funcinfo << "Kopete only found log file made in the future. Check your date!" << endl;
				break;
			}
			return result;
		}
		++it;
	}
	return 0;
}

unsigned int HistoryLogger::getFirstMonth()
{
	if(m_cachedMonth!=-1)
		return m_cachedMonth;

	if(!m_metaContact)
		return 0;

	int m=0;
	TQPtrList<Kopete::Contact> contacts=m_metaContact->contacts();
	TQPtrListIterator<Kopete::Contact> it( contacts );
	for( ; it.current(); ++it )
	{
		int m2=getFirstMonth(*it);
		if(m2>m) m=m2;
	}
	m_cachedMonth=m;
	return m;
}

void HistoryLogger::setHideOutgoing(bool b)
{
	m_hideOutgoing = b;
}

void HistoryLogger::slotMCDeleted()
{
	m_metaContact = 0;
}

void HistoryLogger::setFilter(const TQString& filter, bool caseSensitive , bool isRegExp)
{
	m_filter=filter;
	m_filterCaseSensitive=caseSensitive;
	m_filterRegExp=isRegExp;
}

TQString HistoryLogger::filter() const
{
	return m_filter;
}

bool HistoryLogger::filterCaseSensitive() const
{
	return m_filterCaseSensitive;
}

bool HistoryLogger::filterRegExp() const
{
	return m_filterRegExp;
}

TQValueList<int> HistoryLogger::getDaysForMonth(TQDate date)
{
	TQRegExp rxTime("time=\"(\\d+) \\d+:\\d+(:\\d+)?\""); //(with a 0.7.x compatibility)

	TQValueList<int> dayList;

	TQPtrList<Kopete::Contact> contacts = m_metaContact->contacts();
	TQPtrListIterator<Kopete::Contact> it(contacts);

	int lastDay=0;
	for(; it.current(); ++it)
	{
//		kdDebug() << getFileName(*it, date) << endl;
		TQFile file(getFileName(*it, date));
		if(!file.open(IO_ReadOnly))
		{
			continue;
		}
		TQTextStream stream(&file);
		TQString fullText = stream.read();
		file.close();

		int pos = 0;
		while( (pos = rxTime.search(fullText, pos)) != -1)
		{
			pos += rxTime.matchedLength();
			int day=rxTime.capturedTexts()[1].toInt();
			
			if ( day !=lastDay && dayList.find(day) == dayList.end()) // avoid duplicates
			{
				dayList.append(rxTime.capturedTexts()[1].toInt());
				lastDay=day;
			}
		}
	}
	return dayList;
}

#include "historylogger.moc"
