/***************************************************************************
                          irmcsynckonnector.cpp  -  description
                             -------------------
    begin                : Sat Feb 14 2003
    copyright            : (C) 2003-2005 by Simone Gotti
	
	from the threaded konnector of Mathias Froehlich <Mathias.Froehlich@web.de>
	
    email                : simone.gotti@email.it
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 <kdebug.h>
#include <kgenericfactory.h>
#include <kconfig.h>
#include <konnectorinfo.h>

#include "clientmanager.h"

#include "obexclient.h"
#include "irmcsynckonnector.h"
#include "irmcsyncconfig.h"


using namespace KSync;

extern "C"
{
	void *init_libirmcsynckonnector() {
		return new KRES::PluginFactory<ThreadedPlugin,IrMCSyncConfig>();
	}
}

ThreadedPlugin::ThreadedPlugin( const KConfig *config )
		: Konnector( config ), mConfigWidget( 0l ),
      mObex( 0l ),
      mCalendarClientManager( 0l ),
      mAddressBookClientManager( 0l )
{
	kdDebug() << __PRETTY_FUNCTION__ << " this = " << this << endl;

	if ( config ) {
    mPhoneModel = (IrMCSyncHelper::Device::Model)config->readNumEntry( "PhoneModel", IrMCSyncHelper::Device::Other);
    mType = (Type)config->readNumEntry( "Type", 0 );
		mSyncCalendar =  config->readBoolEntry( "SyncCalendar" );
		mSyncAddressBook = config->readBoolEntry( "SyncAddressBook", true );

		mDeviceBtAddress = config->readEntry( "DeviceBtAddress" );

    mDevicePath = config->readEntry( "Device" );
    mDeviceSpeed = config->readNumEntry( "DeviceSpeed", 57600 );
	} else {
    mPhoneModel = IrMCSyncHelper::Device::Other;
    mType = Bluetooth;
    mSyncCalendar = false;
    mSyncAddressBook = true;
    mDeviceBtAddress = "";
    mDevicePath = "/dev/ttyUSB0";
    mDeviceSpeed = 57600;
  }

  init();
}

void ThreadedPlugin::init()
{
  delete mObex;
  delete mCalendarClientManager;
  delete mAddressBookClientManager;

	// Set the number of Threads;
	threadsNumber = 0;
	if(mSyncCalendar)
		++threadsNumber;
	if(mSyncAddressBook)
		++threadsNumber;

	// Set the Obex Client
	QObexTransport* transport = 0;

  if ( mType == Bluetooth ) {
    QObexBtTransport *btTransport = new QObexBtTransport;
	QString dest = mDeviceBtAddress;
	if ( !dest.isEmpty() )
		btTransport->setDestAddress( dest );

    btTransport->setUuid( QObexBtTransport::IrMCServ );

    transport = btTransport;
  } else {
    QObexBfbTransport *serialTransport = new QObexBfbTransport;
    serialTransport->setDevice( mDevicePath );
    serialTransport->setSpeed( mDeviceSpeed );

    transport = serialTransport;
  }

  transport->setBlocking(true);

	bool verbose = true;

	mObex = new Client( transport, verbose );
	mObex->setUuid( QObexUuidIrMCSync );

	// We have to create the various clientManagers
	if( mSyncCalendar ) {
		mCalendarClientManager = new ClientManager(CalendarSync, mPhoneModel, this);

		connect( mCalendarClientManager, SIGNAL(signalSynceeReaded( KSync::Syncee* )),
		         SLOT(slotSynceeReaded( KSync::Syncee* )) );
		connect( mCalendarClientManager, SIGNAL(signalSynceeWrited()),
		         SLOT(slotSynceeWrited()) );
	}
	
	if( mSyncAddressBook ) {
		mAddressBookClientManager = new ClientManager(AddressBookSync, mPhoneModel, this);

		connect( mAddressBookClientManager, SIGNAL(signalSynceeReaded( KSync::Syncee* )),
		         SLOT(slotSynceeReaded( KSync::Syncee* )) );
		connect( mAddressBookClientManager, SIGNAL(signalSynceeWrited()),
		         SLOT(slotSynceeWrited()) );
	}
}

ThreadedPlugin::~ThreadedPlugin()
{
	kdDebug() << __PRETTY_FUNCTION__ << " this = " << this << endl;

  if ( mCalendarClientManager ) {
//  	mCalendarClientManager->terminate();
//	  mCalendarClientManager->wait();
  }

  if ( mAddressBookClientManager ) {
  //	mAddressBookClientManager->terminate();
//	  mAddressBookClientManager->wait();
  }
}

SynceeList ThreadedPlugin::syncees()
{
	return mSyncees;
}

void ThreadedPlugin::writeConfig( KConfig *config )
{
	kdDebug() << "writeConfig" << endl;

	Konnector::writeConfig( config );

  config->writeEntry( "PhoneModel", mPhoneModel );
  config->writeEntry( "Type", mType );
	config->writeEntry( "SyncCalendar", mSyncCalendar );
	config->writeEntry( "SyncAddressBook", mSyncAddressBook );

	config->writeEntry( "DeviceBtAddress", mDeviceBtAddress );

  config->writeEntry( "Device", mDevicePath );
  config->writeEntry( "DeviceSpeed", mDeviceSpeed );
}

bool ThreadedPlugin::readSyncees()
{
	kdDebug() << __PRETTY_FUNCTION__ << " this = " << this << endl;


	readedSynceesNumber = 0;
	if(mSyncCalendar) {
		kdDebug() << " mSyncCalendar = yes" << endl;
		mCalendarClientManager->setObexClient(mObex);
		return mCalendarClientManager->readSyncees();
	}
	else if(mSyncAddressBook) {
		kdDebug() << " mSyncAddressBook = yes" << endl;
		mAddressBookClientManager->setObexClient(mObex);
		return mAddressBookClientManager->readSyncees();
	}

	return false;
}

bool ThreadedPlugin::writeSyncees()
{
	kdDebug() << __PRETTY_FUNCTION__ << " this = " << this << endl;
	if(mSyncCalendar) {
		kdDebug() << " mSyncCalendar = yes" << endl;
		mCalendarClientManager->setObexClient(mObex);
		return mCalendarClientManager->writeSyncees();
	}
	else if(mSyncAddressBook) {
		kdDebug() << " mSyncAddressBook = yes" << endl;
		mAddressBookClientManager->setObexClient(mObex);
		return mAddressBookClientManager->writeSyncees();
	}
	return false;
}

bool ThreadedPlugin::connectDevice()
{
	kdDebug() << "connectDevice()" << endl;

	return mObex->connectClient();
}

bool ThreadedPlugin::disconnectDevice()
{
	kdDebug() << "disconnectDevice()" << endl;
	/* Free the mSyncees */
	mSyncees.clear();
	return mObex->disconnectClient();
}

KSync::KonnectorInfo ThreadedPlugin::info() const
{
	kdDebug() << __PRETTY_FUNCTION__ << " this = " << this << endl;
	return KSync::KonnectorInfo();
}

QStringList ThreadedPlugin::supportedFilterTypes() const
{
  QStringList types;
  types << "addressbook" << "calendar";

  return types;
}

void ThreadedPlugin::slotSynceeReaded(KSync::Syncee* syncee)
{
	kdDebug() << "slotSynceeReceived()" << endl;

	mSyncees.append(syncee);

	if(++readedSynceesNumber == threadsNumber)
		emit synceesRead( this );
}

void ThreadedPlugin::slotSynceeWrited()
{
	kdDebug() << "slotSynceeWrited" << endl;

	emit synceesWritten( this );
}

#include "irmcsynckonnector.moc"
