/*
    statisticsplugin.cpp

    Copyright (c) 2003-2004 by Marc Cramdal        <marc.cramdal@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.                                   *
    *                                                                       *
    *************************************************************************
*/

#include <tqfile.h>
#include <tqdict.h>
#include <tqtimer.h>

#include <kgenericfactory.h>
#include <tdeaboutdata.h>
#include <tdeaction.h>
#include <tdemessagebox.h>
#include <tdestandarddirs.h>

#include "kopetechatsessionmanager.h"
#include "kopetemetacontact.h"
#include "kopeteview.h"
#include "kopetecontactlist.h"
#include "kopeteuiglobal.h"
#include "kopetemessageevent.h"
#include "kopeteonlinestatus.h"
#include "kopeteaccountmanager.h"
#include "kopeteaccount.h"

#include "statisticscontact.h"
#include "statisticsdialog.h"
#include "statisticsplugin.h"
#include "statisticsdb.h"

typedef KGenericFactory<StatisticsPlugin> StatisticsPluginFactory;


static const TDEAboutData aboutdata("kopete_statistics", I18N_NOOP("Statistics") , "0.1" );
K_EXPORT_COMPONENT_FACTORY( kopete_statistics, StatisticsPluginFactory( &aboutdata )  )

StatisticsPlugin::StatisticsPlugin( TQObject *parent, const char *name, const TQStringList &)
      : DCOPObject("StatisticsDCOPIface"), 
        Kopete::Plugin( StatisticsPluginFactory::instance(), parent, name )
      

{
	TDEAction *viewMetaContactStatistics = new TDEAction( i18n("View &Statistics" ),
		TQString::fromLatin1( "text-x-log" ), 0, this, TQ_SLOT(slotViewStatistics()),
		actionCollection(), "viewMetaContactStatistics" );
	viewMetaContactStatistics->setEnabled(Kopete::ContactList::self()->selectedMetaContacts().count() == 1);

	connect(Kopete::ChatSessionManager::self(),TQ_SIGNAL(chatSessionCreated(Kopete::ChatSession*)),
				this, TQ_SLOT(slotViewCreated(Kopete::ChatSession*)));
	connect(Kopete::ChatSessionManager::self(),TQ_SIGNAL(aboutToReceive(Kopete::Message&)),
				this, TQ_SLOT(slotAboutToReceive(Kopete::Message&)));
		
	connect(Kopete::ContactList::self(), TQ_SIGNAL(metaContactSelected(bool)),
		viewMetaContactStatistics, TQ_SLOT(setEnabled(bool)));
	connect(Kopete::ContactList::self(), TQ_SIGNAL(metaContactAdded(Kopete::MetaContact*)),
			this, TQ_SLOT(slotMetaContactAdded(Kopete::MetaContact*)));	
	connect(Kopete::ContactList::self(), TQ_SIGNAL(metaContactRemoved(Kopete::MetaContact*)),
			this, TQ_SLOT(slotMetaContactRemoved(Kopete::MetaContact*)));	

	setXMLFile("statisticsui.rc");

	/* Initialization reads the database, so it could be a bit time-consuming
	due to disk access. This should overcome the problem and makes it non-blocking. */
	TQTimer::singleShot(0, this, TQ_SLOT(slotInitialize()));
}	

void StatisticsPlugin::slotInitialize()
{
	// Initializes the database
	m_db = new StatisticsDB();
	
	TQPtrList<Kopete::MetaContact> list = Kopete::ContactList::self()->metaContacts();
	TQPtrListIterator<Kopete::MetaContact> it( list );
	for (; it.current(); ++it)
	{
		slotMetaContactAdded(it.current());
	}
}

StatisticsPlugin::~StatisticsPlugin()
{
	TQMap<Kopete::MetaContact*, StatisticsContact*>::Iterator it;
        for ( it = statisticsMetaContactMap.begin(); it != statisticsMetaContactMap.end(); ++it )
	{
		delete it.data();
	}
	delete m_db;
}

void StatisticsPlugin::slotAboutToReceive(Kopete::Message& m)
{
	if ( statisticsMetaContactMap.contains(m.from()->metaContact()) )
		statisticsMetaContactMap[m.from()->metaContact()]->newMessageReceived(m);
}

void StatisticsPlugin::slotViewCreated(Kopete::ChatSession* session)
{
	connect(session, TQ_SIGNAL(closing(Kopete::ChatSession*)), this, TQ_SLOT(slotViewClosed(Kopete::ChatSession*)));
}

void StatisticsPlugin::slotViewClosed(Kopete::ChatSession* session)
{
	TQPtrList<Kopete::Contact> list = session->members();
	TQPtrListIterator<Kopete::Contact> it( list );
	
	for (; it.current(); ++it)
	{
		// If this contact is not in other chat sessions
		if (!it.current()->manager() && statisticsMetaContactMap.contains(it.current()->metaContact()))
			statisticsMetaContactMap[it.current()->metaContact()]->setIsChatWindowOpen(false);
	}
}

void StatisticsPlugin::slotViewStatistics()
{
	Kopete::MetaContact *mc=Kopete::ContactList::self()->selectedMetaContacts().first();
	
	kdDebug() << k_funcinfo << "statistics - dialog :"+ mc->displayName() << endl;
	
	if ( mc && statisticsMetaContactMap.contains(mc) )
	{
		(new StatisticsDialog(statisticsMetaContactMap[mc], db()))->show();
	}
}

void StatisticsPlugin::slotOnlineStatusChanged(Kopete::MetaContact *mc, Kopete::OnlineStatus::StatusType status)
{
	if ( statisticsMetaContactMap.contains(mc) )
		statisticsMetaContactMap[mc]->onlineStatusChanged(status);
}

void StatisticsPlugin::slotMetaContactAdded(Kopete::MetaContact *mc)
{
	statisticsMetaContactMap[mc] = new StatisticsContact(mc, db());
	
	TQPtrList<Kopete::Contact> clist = mc->contacts();
	Kopete::Contact *contact;
	
	// we need to call slotContactAdded if MetaContact allready have contacts
	for ( contact = clist.first(); contact; contact = clist.next() )
	{
		this->slotContactAdded(contact);
	}
	
	connect(mc, TQ_SIGNAL(onlineStatusChanged( Kopete::MetaContact *, Kopete::OnlineStatus::StatusType)), this,
					TQ_SLOT(slotOnlineStatusChanged(Kopete::MetaContact*, Kopete::OnlineStatus::StatusType)));
	connect(mc, TQ_SIGNAL(contactAdded( Kopete::Contact *)), this,
					TQ_SLOT(slotContactAdded( Kopete::Contact *)));
	connect(mc, TQ_SIGNAL(contactRemoved( Kopete::Contact *)), this,
					TQ_SLOT(slotContactRemoved( Kopete::Contact *)));
}

void StatisticsPlugin::slotMetaContactRemoved(Kopete::MetaContact *mc)
{
	if (statisticsMetaContactMap.contains(mc))
	{
		StatisticsContact *sc = statisticsMetaContactMap[mc];
		statisticsMetaContactMap.remove(mc);
		sc->removeFromDB();
		delete sc;
	}
}

void StatisticsPlugin::slotContactAdded( Kopete::Contact *c)
{
	if (statisticsMetaContactMap.contains(c->metaContact()))
	{
		StatisticsContact *sc = statisticsMetaContactMap[c->metaContact()];
		sc->contactAdded(c);
		statisticsContactMap[c->contactId()] = sc;
	}
}

void StatisticsPlugin::slotContactRemoved( Kopete::Contact *c)
{
	if (statisticsMetaContactMap.contains(c->metaContact()))
		statisticsMetaContactMap[c->metaContact()]->contactRemoved(c);
	
	statisticsContactMap.remove(c->contactId());
}

void StatisticsPlugin::dcopStatisticsDialog(TQString id)
{
	kdDebug() << k_funcinfo << "statistics - DCOP dialog :" << id << endl;
	
	if (statisticsContactMap.contains(id))
	{
		(new StatisticsDialog(statisticsContactMap[id], db()))->show();
	}	
}

bool StatisticsPlugin::dcopWasOnline(TQString id, int timeStamp)
{
	TQDateTime dt;
	dt.setTime_t(timeStamp);	
	return dcopWasStatus(id, dt, Kopete::OnlineStatus::Online); 
}

bool StatisticsPlugin::dcopWasOnline(TQString id, TQString dateTime)
{
	return dcopWasStatus(id, TQDateTime::fromString(dateTime), Kopete::OnlineStatus::Online);
}

bool StatisticsPlugin::dcopWasAway(TQString id, int timeStamp)
{
	TQDateTime dt;
	dt.setTime_t(timeStamp);	
	return dcopWasStatus(id, dt, Kopete::OnlineStatus::Away); 
}

bool StatisticsPlugin::dcopWasAway(TQString id, TQString dateTime)
{
	return dcopWasStatus(id, TQDateTime::fromString(dateTime), Kopete::OnlineStatus::Away);
}

bool StatisticsPlugin::dcopWasOffline(TQString id, int timeStamp)
{
	TQDateTime dt;
	dt.setTime_t(timeStamp);	
	return dcopWasStatus(id, dt, Kopete::OnlineStatus::Offline); 
}

bool StatisticsPlugin::dcopWasOffline(TQString id, TQString dateTime)
{
	return dcopWasStatus(id, TQDateTime::fromString(dateTime), Kopete::OnlineStatus::Offline);
}

bool StatisticsPlugin::dcopWasStatus(TQString id, TQDateTime dateTime, Kopete::OnlineStatus::StatusType status)
{
	kdDebug() << k_funcinfo << "statistics - DCOP wasOnline :" << id << endl;
	
	if (dateTime.isValid() && statisticsContactMap.contains(id))
	{
		return statisticsContactMap[id]->wasStatus(dateTime, status);
	}
	
	return false;	
}

TQString StatisticsPlugin::dcopStatus(TQString id, int timeStamp)
{
	TQDateTime dt;
	dt.setTime_t(timeStamp);
	return dcopStatus(id, dt.toString());

}

TQString StatisticsPlugin::dcopStatus(TQString id, TQString dateTime)
{
	TQDateTime dt = TQDateTime::fromString(dateTime);
	
	if (dt.isValid() && statisticsContactMap.contains(id))
	{
		return statisticsContactMap[id]->statusAt(dt);
	}
	
	return "";
}

TQString StatisticsPlugin::dcopMainStatus(TQString id, int timeStamp)
{
	TQDateTime dt;
	dt.setTime_t(timeStamp);
	if (dt.isValid() && statisticsContactMap.contains(id))
	{
		return statisticsContactMap[id]->mainStatusDate(dt.date());
	}
	
	return "";
}
#include "statisticsplugin.moc"
