/*
    tdeconf_update app for migrating kopete 0.6.x accounts to 0.7. Code is
    not up to my normal standards, but it does the job, and since it's
    supposed to run exactly once on each system that's good enough for me :)

    Copyright (c) 2003      by Martijn Klingens <klingens@kde.org>

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

    *************************************************************************
    *                                                                       *
    * This library is free software; you can redistribute it and/or         *
    * modify it under the terms of the GNU Lesser General Public            *
    * License as published by the Free Software Foundation; either          *
    * version 2 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include <tqmap.h>
#include <tqtextstream.h>
#include <tqregexp.h>

static TQTextStream qcin ( stdin,  IO_ReadOnly );
static TQTextStream qcout( stdout, IO_WriteOnly );
static TQTextStream qcerr( stderr, IO_WriteOnly );

// Group cache. Yes, I know global vars are ugly :)
bool needFlush = false;
TQString accountId;
TQString password;
TQString autoConnect;
TQString protocol;
TQMap<TQString, TQString> pluginData;

// Global vars to hold separate IRC vars until we have read all of them
TQString ircNick;
TQString ircServer;
TQString ircPort;

/*
 * Function for (en/de)crypting strings for config file, taken from KMail
 * Author: Stefan Taferner <taferner@alpin.or.at>
 */
TQString cryptStr(const TQString &aStr)
{
	TQString result;
	for (unsigned int i = 0; i < aStr.length(); i++)
		result += (aStr[i].unicode() < 0x20) ? aStr[i] :
			TQChar(0x1001F - aStr[i].unicode());
	return result;
}

void parseGroup( const TQString &group, const TQString &rawLine )
{
	// Groups that are converted can almost certainly be removed entirely

	if ( group == "MSN" || group == "ICQ" || group == "Oscar" || group == "Gadu" || group == "Jabber" || group == "IRC" )
	{
		accountId = "EMPTY";
		autoConnect = "true";

		if ( group == "Oscar" )
			protocol = "AIMProtocol";
		else
			protocol = group + "Protocol";

		password = TQString();
		pluginData.clear();

		needFlush = true;

		qcout << "# DELETEGROUP [" << group << "]" << endl;
	}
	else
	{
		// Groups we don't convert. Output the raw line instead.
		qcout << rawLine << endl;
	}
}

void parseKey( const TQString &group, const TQString &key, const TQString &value, const TQString &rawLine )
{
	//qcerr << "*** group='" << group << "'" << endl;
	if ( group == "MSN" )
	{
		if ( key == "UserID" )
			accountId = value;
		else if ( key == "Password" )
			password = value;
		else if ( key == "AutoConnect" )
			autoConnect = value;
		else if ( key == "Nick" )
			pluginData[ "displayName" ] = value;

		// All other keys are ignored for MSN, as these apply to stuff that's
		// now in libkopete (and the main app) instead.
	}
	else if ( group == "ICQ" )
	{
		if ( key == "UIN" )
			accountId = value;
		else if ( key == "Password" )
			password = value;
		else if ( key == "AutoConnect" )
			autoConnect = value;
		else if ( key == "Nick" )
			pluginData[ "NickName" ] = value;
		else if ( key == "Server" )
			pluginData[ key ] = value;
		else if ( key == "Port" )
			pluginData[ key ] = value;
	}
	else if ( group == "Oscar" )
	{
		if ( key == "ScreenName" )
			accountId = value;
		else if ( key == "Password" )
			password = value;
		else if ( key == "Server" )
			pluginData[ key ] = value;
		else if ( key == "Port" )
			pluginData[ key ] = value;
 	}
	else if ( group == "Jabber" )
	{
		if ( key == "UserID" )
			accountId = value;
		else if ( key == "Password" )
			password = value;
		if ( key == "Server" ||
			 key == "Port" || key == "UseSSL" || key == "Resource" )
			pluginData[ key ] = value;
	}
	else if ( group == "Gadu" )
	{
		if ( key == "UIN" )
			accountId = value;
		else if ( key == "Password" )
			password = value;
		else if ( key == "Nick" )
			pluginData[ "displayName" ] = value;
	}
	else if ( group == "IRC" )
	{
		if ( key == "Nickname" )
			ircNick = value;
		if ( key == "Server" )
			ircServer = value;
		if ( key == "Port" )
			ircPort = value;
		if ( accountId == "EMPTY" &&
			 !ircNick.isEmpty( ) && !ircServer.isEmpty() &&
			 !ircPort.isEmpty() )
		{
			accountId = TQString::fromLatin1( "%1@%2:%3" ).arg( ircNick, ircServer, ircPort );
		}
	}
	/*
		fixme: insert all other plugins here - martijn
	*/
	else if ( key == "Modules" )
	{
		TQString newValue = value;
		newValue.replace ( ".plugin", ".desktop" );
		qcout << "Plugins=" << newValue;
	}
	else
	{
		// groups we don't convert. output the raw line instead.
		qcout << rawLine << endl;
	}
}

void flushData( const TQString &group )
{

	qcout << "[Account_" << protocol << "_" << accountId << "]" << endl;
	qcout << "Protocol=" << protocol << endl;

	if( group == "Jabber" )
		qcout << "AccountId=" << accountId << "@" << pluginData["Server"] << endl;
	else
		qcout << "AccountId=" << accountId << endl;

	qcout << "Password=" << cryptStr( password ) << endl;
	qcout << "AutoConnect=" << autoConnect << endl;

	TQMap<TQString, TQString>::ConstIterator it;
	for ( it = pluginData.begin(); it != pluginData.end(); ++it )
		qcout << "PluginData_" << protocol << "_" << it.key() << "=" << it.data() << endl;

}

int main()
{
	qcin.setEncoding( TQTextStream::UnicodeUTF8 );
	qcout.setEncoding( TQTextStream::UnicodeUTF8 );

	TQString curGroup;

	TQRegExp groupRegExp( "^\\[(.*)\\]" );
	TQRegExp keyRegExp( "^([a-zA-Z0-9:, _-]*)\\s*=\\s*(.*)\\s*" );
	TQRegExp commentRegExp( "^(#.*)?$" );

	while ( !qcin.atEnd() )
	{
		TQString line = qcin.readLine();

		if ( commentRegExp.exactMatch( line ) )
		{
			// We found a comment, leave unchanged
			qcout << line << endl;
		}
		else if ( groupRegExp.exactMatch( line ) )
		{
			// We found the start of a group, parse it
			if ( needFlush )
			{
				// ... but we were already working on a group, so finish what
				// we were doing - flush existing group first
				flushData ( curGroup );
				needFlush = false;
			}

			curGroup = groupRegExp.capturedTexts()[ 1 ];
			parseGroup( curGroup, line );
		}
		else if ( keyRegExp.exactMatch( line ) )
		{
			// We found the a key line
			parseKey( curGroup, keyRegExp.capturedTexts()[ 1 ], keyRegExp.capturedTexts()[ 2 ], line );
		}
		else
		{
			qcerr << "** Unknown input line: " << line << endl;
		}
	}

	if ( needFlush )
		flushData ( curGroup );

	return 0;
}
