/*

    Copyright (c) 2006      by Olivier Goffart  <ogoffart at kde.org>

    Kopete    (c) 2006 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 "jabbertransport.h"
#include "jabbercontact.h"
#include "jabberaccount.h"
#include "jabberprotocol.h"
#include "jabbercontactpool.h"
#include "jabberchatsession.h"

#include <kopeteaccountmanager.h>
#include <kopetecontact.h>
#include <kopetecontactlist.h>

#include <kopeteversion.h>


#include <tqpixmap.h>
#include <tqtimer.h>
#include <tdeaction.h>
#include <kdebug.h>
#include <tdelocale.h>
#include <tdeconfig.h>

#include "xmpp_tasks.h"

JabberTransport::JabberTransport (JabberAccount * parentAccount, const XMPP::RosterItem & item, const TQString& gateway_type)
	: Kopete::Account ( parentAccount->protocol(), parentAccount->accountId()+"/"+ item.jid().bare() )
{
	m_status=Creating;
	m_account = parentAccount;
	m_account->addTransport( this,item.jid().bare() );
	
	JabberContact *myContact = m_account->contactPool()->addContact ( item , Kopete::ContactList::self()->myself(), false );
	setMyself( myContact );
	
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << accountId() <<" transport created:  myself: " << myContact << endl;
	
	setColor( account()->color() );

#if KOPETE_IS_VERSION(0,11,51)  //setCustomIcon is new in kopete 0.12
	TQString cIcon;
	if(gateway_type=="msn")
		cIcon="jabber_gateway_msn";
	else if(gateway_type=="icq")
		cIcon="jabber_gateway_icq";
	else if(gateway_type=="aim")
		cIcon="jabber_gateway_aim";
	else if(gateway_type=="yahoo")
		cIcon="jabber_gateway_yahoo";
	else if(gateway_type=="sms")
		cIcon="jabber_gateway_sms";
	else if(gateway_type=="gadu-gadu")
		cIcon="jabber_gateway_gadu";
	else if(gateway_type=="smtp")
		cIcon="jabber_gateway_smtp";
	else if(gateway_type=="http-ws") 
		cIcon="jabber_gateway_http-ws";
	else if(gateway_type=="qq")
		cIcon="jabber_gateway_qq";
	else if(gateway_type=="tlen")
		cIcon="jabber_gateway_tlen";
	else if(gateway_type=="irc")  //NOTE: this is not official 
		cIcon="irc_protocol";

	if( !cIcon.isEmpty() )
		setCustomIcon( cIcon );
#endif

	configGroup()->writeEntry("GatewayJID" , item.jid().full() );

	TQTimer::singleShot(0, this, TQT_SLOT(eatContacts()));
	
	m_status=Normal;
}

JabberTransport::JabberTransport( JabberAccount * parentAccount, const TQString & _accountId )
	: Kopete::Account ( parentAccount->protocol(), _accountId )
{
	m_status=Creating;
	m_account = parentAccount;
	
	const TQString contactJID_s = configGroup()->readEntry("GatewayJID");
	
	if(contactJID_s.isEmpty())
	{
		kdError(JABBER_DEBUG_GLOBAL) << k_funcinfo << _accountId <<": GatewayJID is empty: MISCONFIGURATION  (have you used Kopete 0.12 beta ?)" << endl;
	}
	
	XMPP::Jid contactJID= XMPP::Jid( contactJID_s );
	
	m_account->addTransport( this, contactJID.bare() );
	
	JabberContact *myContact = m_account->contactPool()->addContact ( contactJID , Kopete::ContactList::self()->myself(), false );
	setMyself( myContact );
	
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << accountId() <<" transport created:  myself: " << myContact << endl;
	
	m_status=Normal;
}




JabberTransport::~JabberTransport ()
{
	m_account->removeTransport( myself()->contactId() );
}

TDEActionMenu *JabberTransport::actionMenu ()
{
	TDEActionMenu *menu = new TDEActionMenu( accountId(), myself()->onlineStatus().iconFor( this ),  this );
	TQString nick = myself()->property( Kopete::Global::Properties::self()->nickName()).value().toString();

	menu->popupMenu()->insertTitle( myself()->onlineStatus().iconFor( myself() ),
	nick.isNull() ? accountLabel() : i18n( "%2 <%1>" ).arg( accountLabel(), nick )
								  );
	
	TQPtrList<TDEAction> *customActions = myself()->customContextMenuActions(  );
	if( customActions && !customActions->isEmpty() )
	{
		menu->popupMenu()->insertSeparator();

		for( TDEAction *a = customActions->first(); a; a = customActions->next() )
			a->plug( menu->popupMenu() );
	}
	delete customActions;

	return menu;

/*	TDEActionMenu *m_actionMenu = Kopete::Account::actionMenu();

	m_actionMenu->popupMenu()->insertSeparator();

	m_actionMenu->insert(new TDEAction (i18n ("Join Groupchat..."), "jabber_group", 0,
		this, TQT_SLOT (slotJoinNewChat ()), this, "actionJoinChat"));

	m_actionMenu->popupMenu()->insertSeparator();

	m_actionMenu->insert ( new TDEAction ( i18n ("Services..."), "jabber_serv_on", 0,
										 this, TQT_SLOT ( slotGetServices () ), this, "actionJabberServices") );

	m_actionMenu->insert ( new TDEAction ( i18n ("Send Raw Packet to Server..."), "mail-message-new", 0,
										 this, TQT_SLOT ( slotSendRaw () ), this, "actionJabberSendRaw") );

	m_actionMenu->insert ( new TDEAction ( i18n ("Edit User Info..."), "identity", 0,
										 this, TQT_SLOT ( slotEditVCard () ), this, "actionEditVCard") );

	return m_actionMenu;*/
}


bool JabberTransport::createContact (const TQString & contactId,  Kopete::MetaContact * metaContact)
{
#if 0 //TODO
	// collect all group names
	TQStringList groupNames;
	Kopete::GroupList groupList = metaContact->groups();
	for(Kopete::Group *group = groupList.first(); group; group = groupList.next())
		groupNames += group->displayName();

	XMPP::Jid jid ( contactId );
	XMPP::RosterItem item ( jid );
	item.setName ( metaContact->displayName () );
	item.setGroups ( groupNames );

	// this contact will be created with the "dirty" flag set
	// (it will get reset if the contact appears in the roster during connect)
	JabberContact *contact = contactPool()->addContact ( item, metaContact, true );

	return ( contact != 0 );
#endif
	return false;
}


void JabberTransport::setOnlineStatus( const Kopete::OnlineStatus& status  , const TQString &reason)
{
#if 0
	if( status.status() == Kopete::OnlineStatus::Offline )
	{
		disconnect( Kopete::Account::Manual );
		return;
	}

	if( isConnecting () )
	{
		errorConnectionInProgress ();
		return;
	}

	XMPP::Status xmppStatus ( "", reason );

	switch ( status.internalStatus () )
	{
		case JabberProtocol::JabberFreeForChat:
			xmppStatus.setShow ( "chat" );
			break;

		case JabberProtocol::JabberOnline:
			xmppStatus.setShow ( "" );
			break;

		case JabberProtocol::JabberAway:
			xmppStatus.setShow ( "away" );
			break;

		case JabberProtocol::JabberXA:
			xmppStatus.setShow ( "xa" );
			break;

		case JabberProtocol::JabberDND:
			xmppStatus.setShow ( "dnd" );
			break;

		case JabberProtocol::JabberInvisible:
			xmppStatus.setIsInvisible ( true );
			break;
	}

	if ( !isConnected () )
	{
		// we are not connected yet, so connect now
		m_initialPresence = xmppStatus;
		connect ();
	}
	else
	{
		setPresence ( xmppStatus );
	}
#endif
}

JabberProtocol * JabberTransport::protocol( ) const
{
	return m_account->protocol(); 
}

bool JabberTransport::removeAccount( )
{
	if(m_status == Removing  ||  m_status == AccountRemoved)
		return true; //so it can be deleted
	
	if (!account()->isConnected())
	{
		account()->errorConnectFirst ();
		return false;
	}
	
	m_status = Removing;
	XMPP::JT_Register *task = new XMPP::JT_Register ( m_account->client()->rootTask () );
	TQObject::connect ( task, TQT_SIGNAL ( finished () ), this, TQT_SLOT ( removeAllContacts() ) );

	//JabberContact *my=static_cast<JabberContact*>(myself());
	task->unreg ( myself()->contactId() );
	task->go ( true );
	return false; //delay the removal
}

void JabberTransport::removeAllContacts( )
{
//	XMPP::JT_Register * task = (XMPP::JT_Register *) sender ();

/*	if ( ! task->success ())
	KMessageBox::queuedMessageBox ( 0L, KMessageBox::Error,
									i18n ("An error occured when trying to remove the transport:\n%1").arg(task->statusString()),
									i18n ("Jabber Service Unregistration"));
	*/ //we don't really care, we remove everithing anyway.

	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "delete all contacts of the transport"<< endl;
	TQDictIterator<Kopete::Contact> it( contacts() ); 
	for( ; it.current(); ++it )
	{
		XMPP::JT_Roster * rosterTask = new XMPP::JT_Roster ( account()->client()->rootTask () );
		rosterTask->remove ( static_cast<JabberBaseContact*>(it.current())->rosterItem().jid() );
		rosterTask->go ( true );
	}
	m_status = Removing; //in theory that's already our status
	Kopete::AccountManager::self()->removeAccount( this ); //this will delete this
}

TQString JabberTransport::legacyId( const XMPP::Jid & jid )
{
	if(jid.node().isEmpty())
		return TQString();
	TQString node = jid.node();
	return node.replace("%","@");
}

void JabberTransport::jabberAccountRemoved( )
{
	m_status = AccountRemoved;
	Kopete::AccountManager::self()->removeAccount( this ); //this will delete this	
}

void JabberTransport::eatContacts( )
{
	/*
	* "Gateway Contact Eating" (c)(r)(tm)(g)(o)(f)
	* this comes directly from my mind into the kopete code.
	* principle: - the transport is hungry
	*            - it will eat contacts which belong to him
	*            - the contact will die
	*            - a new contact will born, with the same characteristics, but owned by the transport
	* - Olivier 2006-01-17 -
	*/
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << endl;
	TQDict<Kopete::Contact> cts=account()->contacts();
	TQDictIterator<Kopete::Contact> it( cts ); 
	for( ; it.current(); ++it )
	{
		JabberContact *contact=dynamic_cast<JabberContact*>(it.current());
		if( contact && !contact->transport() && contact->rosterItem().jid().domain() == myself()->contactId() && contact != account()->myself())
		{
			XMPP::RosterItem item=contact->rosterItem();
			Kopete::MetaContact *mc=contact->metaContact();
			Kopete::OnlineStatus status = contact->onlineStatus();
			kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << item.jid().full() << " will be soon eat  - " << contact << endl;
			delete contact;
			Kopete::Contact *c2=account()->contactPool()->addContact( item , mc , false ); //not sure this is false;
			if(c2)
				c2->setOnlineStatus( status ); //put back the old status
		}
	}
}



#include "jabbertransport.moc"

// vim: set noet ts=4 sts=4 sw=4: