/***************************************************************************
                          resource.cpp  -  description
                             -------------------
    begin                : Tue Jul 17 2001
    copyright            : (C) 2003 by Troy Corbin Jr.
    email                : tcorbin@users.sourceforge.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
/* KDE */
#include <kstddirs.h>
#include <tdeglobalsettings.h>
#include <ksimpleconfig.h>
#include <tdeconfig.h>
#include <kiconloader.h>
#include <kmdcodec.h>
#include <tdeio/netaccess.h>
/* TQt */
#include <tqdir.h>
#include <tqimage.h>
/* Local */
#include "resource.h"
#include "audio.h"
#include "knightspixcache.h"
#include "tabmanager.h"
#include "accel.h"
/* C & C++ */
#include <unistd.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <pwd.h>
#include <time.h>

#define CFG kapp->config()
///////////////////////////////////////
//
//	resource::resource
//
///////////////////////////////////////
resource::resource(TDECmdLineArgs *args)
{
	GlobalDataDir = "";
	Widget_Height = 20; // prevents max_size error for thinbuttons on init
	Icons = new TDEIconLoader( TQString( "knights" ) );
	Audio = new audio();

	/* Define ConsoleStyle, our RichText */
	ConsoleStyle = new TQStyleSheet( 0, "ConsoleStyle" );
	SSI_Default = new TQStyleSheetItem( ConsoleStyle, "K_STD" );
	SSI_PrivateTell = new TQStyleSheetItem( ConsoleStyle, "K_PVT" );
	SSI_ChannelTell = new TQStyleSheetItem( ConsoleStyle, "K_CH" );
	SSI_Shout = new TQStyleSheetItem( ConsoleStyle, "K_SHT" );
	SSI_Whisper = new TQStyleSheetItem( ConsoleStyle, "K_WSP" );
	SSI_Notification = new TQStyleSheetItem( ConsoleStyle, "K_NOT" );
	TQStyleSheet::setDefaultSheet( ConsoleStyle );

	/* Define GlobalDataDir... This is very important! */
	GlobalDataDir = args->getOption( "d" );
	if( GlobalDataDir.isEmpty() )
		GlobalDataDir = TDEGlobal::dirs()->findResourceDir("data", "knights/splash.png") + "knights/";
	if( GlobalDataDir.isEmpty() )
	{
		kdWarning() << "resource::resource: Can not read GlobalDataDir from environment." << endl;
		GlobalDataDir = "/usr/local/kde/";
	}
	if( GlobalDataDir.right(1) != "/" ) GlobalDataDir += '/';

	/* Allocate Accel */
	myAccel = new Accel( tqApp->mainWidget() );

	/* Allocate TabManager */
	tabManager = new TabManager( this );

	ConfigRead();
	pixCache = new KnightsPixCache();
	pixCache->setCacheLimit( 2048 ); // 2meg
}
///////////////////////////////////////
//
//	resource::~resource
//
///////////////////////////////////////
resource::~resource()
{
	ConfigWrite();
	delete Icons;
	delete pixCache;
	delete Audio;
	delete tabManager;
	delete myAccel;

	/* Remove temp files that we missed
	TQStringList temps = TDEGlobal::dirs()->findAllResources("tmp","knights*");
	for( int a=0; a < temps.count(); a++)
	{
		TDEIO::NetAccess::del( "file://" + temps[a] );
	} */
}
///////////////////////////////////////
//
//	resource::ConfigRead
//
///////////////////////////////////////
void resource::ConfigRead( void )
{
	struct passwd *passwd;
	TQString sysName;
	TQString buffer;
	TQDesktopWidget *desktop = TQApplication::desktop();

	/* Get Initial Board Size In Case This Install Is New */
	int initSize = ( desktop->height() >> 3 ) - 32;
	if( initSize > IMAGE_MAX )
		initSize = IMAGE_MAX;
	if( initSize < IMAGE_MIN )
		initSize = IMAGE_MIN;

	/* Get user name from environment in case it's needed */
	passwd = getpwuid( getuid() );
	sysName = passwd->pw_gecos;
	if( sysName.isEmpty() )
		sysName = TQStringList::split( ",", TQString(passwd->pw_name) ).first();

	/* Cursors */
	CURSOR_Standard = KCursor::arrowCursor();
	CURSOR_Thinking = KCursor::waitCursor();
	CURSOR_Text = KCursor::ibeamCursor();

	/* Themes */
	readThemeDir();
	CFG->setGroup( "Themes" );
	CurrentBoard = CFG->readEntry( "CurrentBoard", "KBDefault.tar.gz" );
	CurrentChessmen = CFG->readEntry( "CurrentChessmen", "KCDefault.tar.gz" );
	OPTION_3DBoard = CFG->readBoolEntry( "Use3DBoard", FALSE );
	ThemeSize = CFG->readNumEntry( "Size", initSize );
	if( ThemeSize > ( initSize + 16 ) )
		ThemeSize = initSize;
	
	/* General */
	ReadEngines();
	ReadServers();
	ReadMatchParam();
	ReadColors();
	ReadFonts();
	buildStyle();
	CFG->setGroup( "General" );
	Local_Player = CFG->readEntry( "UserName", sysName );
	Config_Version = CFG->readNumEntry( "ConfigVersion", 0 );
	OPTION_On_Init = CFG->readNumEntry( "OnInit", MENU_VS_PC );
	OPTION_Auto_Queen = CFG->readBoolEntry( "AlwaysQueen", FALSE );
	OPTION_Ponder = CFG->readBoolEntry( "Ponder", TRUE );
	OPTION_Book_White = CFG->readBoolEntry( "BookWhite", FALSE );
	OPTION_Book_Black = CFG->readBoolEntry( "BookBlack", FALSE );
	OPTION_Pause_On_Minimize = CFG->readBoolEntry( "PauseOnMinimize", TRUE );
	OPTION_Delete_Logs = CFG->readBoolEntry( "DeleteLogOnExit", FALSE );
	OPTION_Reuse_PGN = CFG->readBoolEntry( "ReusePGN", FALSE );
	PGN_Filename = CFG->readEntry( "PGNFilename", TQString() );
	SCID_Image_Path = CFG->readEntry( "SCIDImages", TQString() );
	OPTION_Auto_Close_Last_ICS = CFG->readBoolEntry( "AutoCloseLastICS", TRUE );
	OPTION_Show_Extended_PGN = CFG->readBoolEntry( "ShowExtendedPGN", FALSE );
	OPTION_Auto_Call_Flag = CFG->readBoolEntry( "AutoCallFlag", TRUE );
	Email_Command_Line = CFG->readEntry( "EmailCommandLine", TQString("kmail -s %s --attach %m %a") );
	Accepted_License = CFG->readBoolEntry( "Alg2p", FALSE );

	/* Display */
	OPTION_Show_Splash = CFG->readBoolEntry( "ShowSplash", TRUE );
	OPTION_Auto_Preview = CFG->readBoolEntry( "AutoPreview", FALSE );
	OPTION_Show_Last_Move = CFG->readBoolEntry( "ShowLastMove", TRUE );
	OPTION_Animate_Moves = CFG->readBoolEntry( "AnimateMoves", FALSE );
	OPTION_Show_Coord = CFG->readBoolEntry( "ShowCoord", FALSE );
	OPTION_Board_Orientation = CFG->readBoolEntry( "BoardOrientation", 0 );

	/* ICS */
	CFG->setGroup( "ICS" );
	OPTION_Premove = CFG->readBoolEntry( "Premove", TRUE );
	OPTION_Kibitz = CFG->readBoolEntry( "Kibitz", TRUE );
	OPTION_Private = CFG->readBoolEntry( "Private", FALSE );
	OPTION_Shout = CFG->readBoolEntry( "Shout", TRUE );
	OPTION_Tell = CFG->readBoolEntry( "Tell", TRUE );
	OPTION_Seek = CFG->readBoolEntry( "Seek", TRUE );
	OPTION_Profanity = CFG->readNumEntry( "Profanity", 1 );
	Seek_Timer = CFG->readNumEntry( "SeekTimer", 70 );

	/* Audio */
	CFG->setGroup( "Audio" );
	OPTION_Audio = CFG->readBoolEntry( "useAudio", TRUE );
	CurrentAudio = CFG->readEntry( "CurrentAudio", "KSDefault.tar.gz" );
	OPTION_Audio_Current_Only = CFG->readBoolEntry( "AudioCurrentOnly", FALSE );
	Audio_Volume = CFG->readNumEntry( "AudioVolume", 0 );
	Audio->enabled = OPTION_Audio;
	Audio->volume = Audio_Volume;

	/* Notification Prompts */
	CFG->setGroup( "Notification Messages" );
	PromptForSaving = CFG->readEntry( "PromptForSaving", TQString() );
}
///////////////////////////////////////
//
//	resource::ConfigWrite
//
///////////////////////////////////////
void resource::ConfigWrite( void )
{
	/* Themes */
	CFG->setGroup( "Themes" );
	CFG->writeEntry( "CurrentBoard", CurrentBoard );
	CFG->writeEntry( "CurrentChessmen", CurrentChessmen );
	CFG->writeEntry( "Size", ThemeSize );
	CFG->writeEntry( "Use3DBoard", OPTION_3DBoard );

	/* General */
	WriteEngines();
	WriteServers();
	WriteMatchParam();
	WriteColors();
	WriteFonts();
	CFG->setGroup( "General" );
	CFG->writeEntry( "UserName", Local_Player );
	CFG->writeEntry( "ConfigVersion", Config_Version );
	CFG->writeEntry( "OnInit", OPTION_On_Init );
	CFG->writeEntry( "ShowSplash", OPTION_Show_Splash );
	CFG->writeEntry( "AlwaysQueen", OPTION_Auto_Queen );
	CFG->writeEntry( "AutoPreview", OPTION_Auto_Preview );
	CFG->writeEntry( "ShowLastMove", OPTION_Show_Last_Move );
	CFG->writeEntry( "AnimateMoves", OPTION_Animate_Moves );
	CFG->writeEntry( "ShowCoord", OPTION_Show_Coord );
	CFG->writeEntry( "Ponder", OPTION_Ponder );
	CFG->writeEntry( "BookWhite", OPTION_Book_White );
	CFG->writeEntry( "BookBlack", OPTION_Book_Black );
	CFG->writeEntry( "BoardOrientation", OPTION_Board_Orientation );
	CFG->writeEntry( "PauseOnMinimize", OPTION_Pause_On_Minimize );
	CFG->writeEntry( "DeleteLogOnExit", OPTION_Delete_Logs );
	CFG->writeEntry( "ReusePGN", OPTION_Reuse_PGN );
	CFG->writeEntry( "PGNFilename", PGN_Filename );
	CFG->writeEntry( "AutoCloseLastICS", OPTION_Auto_Close_Last_ICS );
	CFG->writeEntry( "ShowExtendedPGN", OPTION_Show_Extended_PGN );
	CFG->writeEntry( "EmailCommandLine", Email_Command_Line );
	CFG->writeEntry( "AutoCallFlag", OPTION_Auto_Call_Flag );
	CFG->writeEntry( "SCIDImages", SCID_Image_Path );
	CFG->writeEntry( "Alg2p", Accepted_License );

	/* ICS */
	CFG->setGroup( "ICS" );
	CFG->writeEntry( "SeekTimer", Seek_Timer );
	CFG->writeEntry( "Profanity", OPTION_Profanity );
	CFG->writeEntry( "Premove", OPTION_Premove );
	CFG->writeEntry( "Shout", OPTION_Shout );
	CFG->writeEntry( "Kibitz", OPTION_Kibitz );
	CFG->writeEntry( "Private", OPTION_Private );
	CFG->writeEntry( "Tell", OPTION_Tell );
	CFG->writeEntry( "Seek", OPTION_Seek );

	/* Audio */
	CFG->setGroup( "Audio" );
	CFG->writeEntry( "useAudio", OPTION_Audio );
	Audio->enabled = OPTION_Audio;
	CFG->writeEntry( "CurrentAudio", CurrentAudio );
	CFG->writeEntry( "AudioCurrentOnly", OPTION_Audio_Current_Only );
	CFG->writeEntry( "AudioVolume", Audio_Volume );
	Audio->volume = Audio_Volume;

	/* Notification Prompts */
	CFG->setGroup( "Notification Messages" );
	CFG->writeEntry( "PromptForSaving", PromptForSaving );
	CFG->setReadOnly( FALSE );
	if( CFG->isReadOnly() )
		kdWarning() << "resource::ConfigWrite: Configuration is READ ONLY. Can not write changes." << endl;
	CFG->sync();
}
///////////////////////////////////////
//
//	resource::ReadMatchParam
//
///////////////////////////////////////
void resource::ReadMatchParam( void )
{
	TQString buffer;
	TQStringList TCPs;
	TQStringList::Iterator TQSL_IT;
	TCP tempTCP;

	TCPWhite.clear();
	TCPBlack.clear();
	CFG->setGroup( "Match Paramaters" );

	/* Handle Time Controls */
	buffer = CFG->readEntry( "WhiteTCP", "40,900,0" );
	TCPs = TQStringList::split( TQString(","), buffer, FALSE );
	for( TQSL_IT = TCPs.begin(); TQSL_IT != TCPs.end(); ++TQSL_IT )
	{
		tempTCP.Moves = (*TQSL_IT).toInt();
		++TQSL_IT;
		tempTCP.Seconds = (*TQSL_IT).toInt();
		++TQSL_IT;
		tempTCP.Increment = (*TQSL_IT).toInt();
		TCPWhite.append( tempTCP );
	}
	TCPs.clear();
	buffer = CFG->readEntry( "BlackTCP", "40,900,0" );
	TCPs = TQStringList::split( TQString(","), buffer, FALSE );
	for( TQSL_IT = TCPs.begin(); TQSL_IT != TCPs.end(); ++TQSL_IT )
	{
		tempTCP.Moves = (*TQSL_IT).toInt();
		++TQSL_IT;
		tempTCP.Seconds = (*TQSL_IT).toInt();
		++TQSL_IT;
		tempTCP.Increment = (*TQSL_IT).toInt();
		TCPBlack.append( tempTCP );
	}

	/* Match Rules */
	MatchRules = CFG->readNumEntry( "MatchRules", Type_Standard );

	/* Handle Players */
	Type[WHITE] = CFG->readNumEntry( "WhiteType", PLAYERLOCAL );
	Type[WHITE_HELPER] = CFG->readNumEntry( "WhiteHelperType", PLAYERPC );
	Type[BLACK] = CFG->readNumEntry( "BlackType", PLAYERLOCAL );
	Type[BLACK_HELPER] = CFG->readNumEntry( "BlackHelperType", PLAYERPC );

	Strength[WHITE] = CFG->readNumEntry( "WhiteStr", 18 );
	Strength[WHITE_HELPER] = CFG->readNumEntry( "WhiteHelperStr", 18 );
	Strength[BLACK] = CFG->readNumEntry( "BlackStr", 18 );
	Strength[BLACK_HELPER] = CFG->readNumEntry( "BlackHelperStr", 18 );
}
///////////////////////////////////////
//
//	resource::WriteMatchParam
//
///////////////////////////////////////
void resource::WriteMatchParam( void )
{
	TQString buffer;
	TCPList::Iterator TCP_IT;

	CFG->setGroup( "Match Paramaters" );
	/* Handle Time Controls */
	for( TCP_IT = TCPWhite.begin(); TCP_IT != TCPWhite.end(); ++TCP_IT )
	{
		buffer += TQString::number( (*TCP_IT).Moves ) + ",";
		buffer += TQString::number( (*TCP_IT).Seconds ) + ",";
		buffer += TQString::number( (*TCP_IT).Increment ) + ",";
	}
	CFG->writeEntry( "WhiteTCP", buffer );
	buffer = "";
	for( TCP_IT = TCPBlack.begin(); TCP_IT != TCPBlack.end(); ++TCP_IT )
	{
		buffer += TQString::number( (*TCP_IT).Moves ) + ",";
		buffer += TQString::number( (*TCP_IT).Seconds ) + ",";
		buffer += TQString::number( (*TCP_IT).Increment ) + ",";
	}
	CFG->writeEntry( "BlackTCP", buffer );
	/* Match Rules */
	CFG->writeEntry( "MatchRules", MatchRules );
	/* Handle Players */
	CFG->writeEntry( "WhiteType", Type[WHITE] );
	CFG->writeEntry( "WhiteHelperType", Type[WHITE_HELPER] );
	CFG->writeEntry( "BlackType", Type[BLACK] );
	CFG->writeEntry( "BlackHelperType", Type[BLACK_HELPER] );

	CFG->writeEntry( "WhiteStr", Strength[WHITE] );
	CFG->writeEntry( "WhiteHelperStr", Strength[WHITE_HELPER] );
	CFG->writeEntry( "BlackStr", Strength[BLACK] );
	CFG->writeEntry( "BlackHelperStr", Strength[BLACK_HELPER] );
}
///////////////////////////////////////
//
//	resource::ReadEngines
//
///////////////////////////////////////
void resource::ReadEngines( void )
{
	engineResource temp;
	TQStringList engineList;
	TQStringList::Iterator engineListIT;
	TQString buffer;

	engines.clear();
	CFG->setGroup( "General" );
	buffer = CFG->readEntry( "Engines" );
	if( buffer.isEmpty() ) return;

	engineList = TQStringList::split( TQString(","), buffer, FALSE );
	for ( engineListIT = engineList.begin(); engineListIT != engineList.end(); ++engineListIT )
	{
		if( !CFG->hasGroup( (*engineListIT) ) ) continue;
		CFG->setGroup( (*engineListIT) );
		temp.Name = (*engineListIT);
		temp.Filename = CFG->readEntry( "Filename" );
		temp.Arguments = CFG->readEntry( "Arguments" );
		temp.LogFile = CFG->readEntry( "Log" );
		temp.Protocol = CFG->readNumEntry( "Protocol" );
		temp.Wins = CFG->readNumEntry( "Wins" );
		temp.Losses = CFG->readNumEntry( "Losses" );
		temp.Draws = CFG->readNumEntry( "Draws" );
		temp.CurrentRef = CFG->readNumEntry( "CurrentRef" );
		engines.append( temp );
	}
}
///////////////////////////////////////
//
//	resource::WriteEngines
//
///////////////////////////////////////
void resource::WriteEngines( void )
{
	TQString buffer;

	CFG->setGroup( "General" );
	if( engines.isEmpty() )
	{
		CFG->writeEntry( "Engines", TQString( "" ) );
		return;
	}
	for ( enginesIT = engines.begin(); enginesIT != engines.end(); ++enginesIT )
	{
		buffer += (*enginesIT).Name + ",";
		CFG->setGroup( (*enginesIT).Name );
		CFG->writeEntry( "Filename", (*enginesIT).Filename );
		CFG->writeEntry( "Arguments", (*enginesIT).Arguments );
		CFG->writeEntry( "Log", (*enginesIT).LogFile );
		CFG->writeEntry( "Protocol", (*enginesIT).Protocol );
		CFG->writeEntry( "Wins", (*enginesIT).Wins );
		CFG->writeEntry( "Losses", (*enginesIT).Losses );
		CFG->writeEntry( "Draws", (*enginesIT).Draws );
		CFG->writeEntry( "CurrentRef", (*enginesIT).CurrentRef );
	}
	CFG->setGroup( "General" );
	CFG->writeEntry( "Engines", buffer );
	CFG->sync();
}
///////////////////////////////////////
//
//	resource::ReadServers
//
///////////////////////////////////////
void resource::ReadServers( void )
{
	serverResource temp;
	TQStringList serverList;
	TQStringList::Iterator serverListIT;
	TQString buffer;

	servers.clear();
	CFG->setGroup( "General" );
	buffer = CFG->readEntry( "Servers" );
	if( buffer.isEmpty() ) return;

	serverList = TQStringList::split( TQString(","), buffer, FALSE );
	for ( serverListIT = serverList.begin(); serverListIT != serverList.end(); ++serverListIT )
	{
		if( !CFG->hasGroup( (*serverListIT) ) ) continue;
		CFG->setGroup( (*serverListIT) );
		temp.Name = (*serverListIT);
		temp.URL = CFG->readEntry( "URL" );
		temp.UserName = CFG->readEntry( "UserName" );
		temp.LogFile = CFG->readEntry( "LogFile" );
		temp.Password = decryptStr( CFG->readEntry( "Password" ) );
		temp.StorePass = CFG->readBoolEntry( "StorePass" );
		temp.Port = CFG->readNumEntry( "Port" );
		temp.CurrentRef = CFG->readNumEntry( "CurrentRef" );
		temp.Timeseal = CFG->readEntry( "Timeseal" );
		servers.append( temp );
	}
}
///////////////////////////////////////
//
//	resource::WriteServers
//
///////////////////////////////////////
void resource::WriteServers( void )
{
	TQString buffer;

	CFG->setGroup( "General" );
	if( servers.isEmpty() )
	{
		CFG->writeEntry( "Servers", TQString( "" ) );
		return;
	}
	for ( serversIT = servers.begin(); serversIT != servers.end(); ++serversIT )
	{
		buffer += (*serversIT).Name + ",";
		CFG->setGroup( (*serversIT).Name );
		CFG->writeEntry( "URL", (*serversIT).URL );
		CFG->writeEntry( "UserName", (*serversIT).UserName );
		CFG->writeEntry( "LogFile", (*serversIT).LogFile );
		if( (*serversIT).StorePass )
			CFG->writeEntry( "Password", encryptStr( (*serversIT).Password ) );
		else
			CFG->writeEntry( "Password", "" );
		CFG->writeEntry( "Port", (*serversIT).Port );
		CFG->writeEntry( "StorePass", (*serversIT).StorePass );
		CFG->writeEntry( "CurrentRef", (*serversIT).CurrentRef );
		CFG->writeEntry( "Timeseal", (*serversIT).Timeseal );
	}
	CFG->setGroup( "General" );
	CFG->writeEntry( "Servers", buffer );
	CFG->sync();
}
///////////////////////////////////////
//
//	resource::themeDir
//
///////////////////////////////////////
TQString resource::themeDir( void )
{
	return TQString( GlobalDataDir + "themes/" );
}
///////////////////////////////////////
//
//	resource::readThemeDir
//
///////////////////////////////////////
void resource::readThemeDir( void )
{
	TQDir themesDir;
	
	Boards.clear();
	Chessmen.clear();
	Sounds.clear();
	
	themesDir.setNameFilter( "KB*" );
	themesDir = GlobalDataDir + "themes/";
	Boards += themesDir.entryList();
	themesDir = TQDir::homeDirPath() + "/.knights/";
	if( themesDir.exists() ) Boards += themesDir.entryList();
	themesDir = "../media/";
	if( themesDir.exists() ) Boards += themesDir.entryList();
	Boards.sort();
	
	themesDir.setNameFilter( "KC*" );
	themesDir = GlobalDataDir + "themes/";
	Chessmen += themesDir.entryList();
	themesDir = TQDir::homeDirPath() + "/.knights/";
	if( themesDir.exists() ) Chessmen += themesDir.entryList();
	themesDir = "../media/";
	if( themesDir.exists() ) Chessmen += themesDir.entryList();
	Chessmen.sort();

	themesDir.setNameFilter( "KS*" );
	themesDir = GlobalDataDir + "themes/";
	Sounds += themesDir.entryList();
	themesDir = TQDir::homeDirPath() + "/.knights/";
	if( themesDir.exists() ) Sounds += themesDir.entryList();
	themesDir = "../media/";
	if( themesDir.exists() ) Sounds += themesDir.entryList();
	Sounds.sort();
}
///////////////////////////////////////
//
//	resource::getBoard
//
///////////////////////////////////////
TQString resource::getBoard( int Index )
{
	if( Index > (signed)Boards.count() ) return TQString();
	if( Index == -1 ) return CurrentBoard;
	return  Boards[Index];
}
///////////////////////////////////////
//
//	resource::getChessmen
//
///////////////////////////////////////
TQString resource::getChessmen( int Index )
{
	if( Index > (signed)Chessmen.count() ) return TQString();
	if( Index == -1 ) return CurrentChessmen;
	return  Chessmen[Index];
}
///////////////////////////////////////
//
//	resource::getSounds
//
///////////////////////////////////////
TQString resource::getSounds( int Index )
{
	if( Index > (signed)Sounds.count() ) return TQString();
	if( Index == -1 ) return CurrentAudio;
	return Sounds[Index];
}
///////////////////////////////////////
//
//	resource::setAudio
//
///////////////////////////////////////
void resource::setAudio( int AudioIndex )
{
	TQString audioURL;
	
	/* Make sure the Indexes are valid */
	if( AudioIndex > (signed)Sounds.count() )
	{
		kdWarning() << "Can not access audio theme[" << AudioIndex << "]... Index out of range." << endl;
		return;
	}
	/* Change the theme */
	if( AudioIndex != -1 ) CurrentAudio = Sounds[AudioIndex];
	audioURL = themeURL( CurrentAudio );
	if( audioURL.isEmpty() )
	{
		return;
	}
	TQApplication::setOverrideCursor( CURSOR_Thinking );
	Audio->setTheme( audioURL );
	TQApplication::restoreOverrideCursor();
	return;
}
///////////////////////////////////////
//
//	resource::setTheme
//
///////////////////////////////////////
void resource::setTheme( int BoardIndex, int ChessmenIndex )
{
	static bool firstTime( TRUE );
	TQString boardURL;
	TQString chessmenURL;
	TQString boardConf;
	TQString chessmenConf;
	KSimpleConfig *boardConfig;
	KSimpleConfig *chessmenConfig;
	
	/* Make sure the Indexes are valid */
	if( BoardIndex > (signed)Boards.count() )
	{
		kdWarning() << "Can not access board theme[" << BoardIndex << "]... Index out of range." << endl;
		return;
	}
	if( ChessmenIndex > (signed)Chessmen.count() )
	{
		kdWarning() << "Can not access chessmen theme[" << ChessmenIndex << "]... Index out of range." << endl;
		return;
	}

	/* Set the Cursor */
	TQApplication::setOverrideCursor( CURSOR_Thinking );

	/* Change the theme */
	if( BoardIndex != -1 )
		CurrentBoard = Boards[BoardIndex];
	if( ChessmenIndex != -1 )
		CurrentChessmen = Chessmen[ChessmenIndex];

	boardURL = themeURL( CurrentBoard );
	chessmenURL = themeURL( CurrentChessmen );

	if( ( boardURL.isEmpty() ) || ( chessmenURL.isEmpty() ) )
	{
		TQApplication::restoreOverrideCursor();
		return;
	}

	/* load the theme.conf files */
	if( !TDEIO::NetAccess::download( boardURL + "theme.conf", boardConf ) )
		kdWarning() << "Can not read theme.conf from " << boardURL << endl;
	boardConfig = new KSimpleConfig( boardConf, TRUE );

	if( !TDEIO::NetAccess::download( chessmenURL + "theme.conf", chessmenConf ) )
		kdWarning() << "Can not read theme.conf from " << chessmenURL << endl;
	chessmenConfig = new KSimpleConfig( chessmenConf, TRUE );

	/* Read the headers */
	boardConfig->setGroup( "General" );
	boardHeader.name = boardConfig->readEntry( "Name", "Unknown" );
	boardHeader.version = boardConfig->readEntry( "Version", "Unknown" );
	boardHeader.author = boardConfig->readEntry( "Author", "Unknown" );
	boardHeader.authorEmail = boardConfig->readEntry( "AuthorEmail", "Unknown" );
	boardHeader.authorWWW = boardConfig->readEntry( "AuthorWWW", "Unknown" );
	boardHeader.notes = boardConfig->readEntry( "Notes", "Unknown" );
	chessmenConfig->setGroup( "General" );
	chessmenHeader.name = chessmenConfig->readEntry( "Name", "Unknown" );
	chessmenHeader.version = chessmenConfig->readEntry( "Version", "Unknown" );
	chessmenHeader.author = chessmenConfig->readEntry( "Author", "Unknown" );
	chessmenHeader.authorEmail = chessmenConfig->readEntry( "AuthorEmail", "Unknown" );
	chessmenHeader.authorWWW = chessmenConfig->readEntry( "AuthorWWW", "Unknown" );
	chessmenHeader.notes = chessmenConfig->readEntry( "Notes", "Unknown" );

	/* Load the Board */
	boardConfig->setGroup( "2DBoard" );
	ThemeBorder = boardConfig->readBoolEntry( "HaveBorder", FALSE );
	loadThemeItem( boardURL + boardConfig->readEntry("Light", "square.light.png"), pixCache->Orig_SquareLight );
	loadThemeItem( boardURL + boardConfig->readEntry("Dark", "square.dark.png"), pixCache->Orig_SquareDark );
	loadThemeItem( boardURL + boardConfig->readEntry("Select", "square.select.png"), pixCache->Orig_HighlightSelect );
	loadThemeItem( boardURL + boardConfig->readEntry("Motion", "square.motion.png"), pixCache->Orig_HighlightMove );
	loadThemeItem( boardURL + boardConfig->readEntry("Danger", "square.danger.png"), pixCache->Orig_HighlightAttack );
	if( ThemeBorder )
	{
		loadThemeItem( boardURL + boardConfig->readEntry("Border", "border.png"), pixCache->Orig_Border );
		loadThemeItem( boardURL + boardConfig->readEntry("BorderLightOn", "light_on.png"), pixCache->Orig_BorderLightOn );
		loadThemeItem( boardURL + boardConfig->readEntry("BorderLightOff", "light_off.png"), pixCache->Orig_BorderLightOff );
	}
	boardConfig->setGroup( "2DBoard" );
	COLOR_Notation = boardConfig->readColorEntry( "TextColor", &COLOR_White );
	COLOR_Notation_Shadow = boardConfig->readColorEntry( "ShadowColor", &COLOR_Black );

	/* Load 2D Chessmen */
	chessmenConfig->setGroup( "2DBlack" );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("King", "black.king.png"), pixCache->Orig_BlackKing );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("Queen", "black.queen.png"), pixCache->Orig_BlackQueen );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("Bishop", "black.bishop.png"), pixCache->Orig_BlackBishop );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("Knight", "black.knight.png"), pixCache->Orig_BlackKnight );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("Rook", "black.rook.png"), pixCache->Orig_BlackRook );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("Pawn", "black.pawn.png"), pixCache->Orig_BlackPawn );
	chessmenConfig->setGroup( "2DWhite" );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("King", "white.king.png"), pixCache->Orig_WhiteKing );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("Queen", "white.queen.png"), pixCache->Orig_WhiteQueen );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("Bishop", "white.bishop.png"), pixCache->Orig_WhiteBishop );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("Knight", "white.knight.png"), pixCache->Orig_WhiteKnight );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("Rook", "white.rook.png"), pixCache->Orig_WhiteRook );
	loadThemeItem( chessmenURL + chessmenConfig->readEntry("Pawn", "white.pawn.png"), pixCache->Orig_WhitePawn );

	/* Remove the theme.conf files */
	delete boardConfig;
	delete chessmenConfig;
	TDEIO::NetAccess::removeTempFile( boardConf );
	TDEIO::NetAccess::removeTempFile( chessmenConf );

	/* Cleanup */
	pixCache->clear();
	TQApplication::restoreOverrideCursor();
	pixCache->resize( ThemeSize );
	firstTime = FALSE;
	return;
}
///////////////////////////////////////
//
//	resource::loadThemeItem
//
///////////////////////////////////////
void resource::loadThemeItem( const TQString &URL, TQImage &Image )
{
	TQString tempFile;
	
	if( TDEIO::NetAccess::download( URL, tempFile ) )
	{
		if( !Image.load( tempFile ) )
			kdError() << "resource::LoadThemeItem: Can not load " << tempFile << ", which comes from " << URL << endl;
		TDEIO::NetAccess::removeTempFile( tempFile );
	}
	else
		kdError() << "resource::LoadThemeItem: Can not extract " << URL << endl;
	return;
}
///////////////////////////////////////
//
//	resource::resizeTheme
//
///////////////////////////////////////
void resource::resizeTheme( const int &size )
{
	/* Set the Cursor */
	TQApplication::setOverrideCursor( CURSOR_Thinking );

	ThemeSize = size;
	if( ThemeSize > IMAGE_MAX )
		ThemeSize = IMAGE_MIN;
	if( ThemeSize < IMAGE_MIN )
		ThemeSize = IMAGE_MAX;
	pixCache->resize( ThemeSize );
	ConfigWrite();

	TQApplication::restoreOverrideCursor();
}
///////////////////////////////////////
//
//	resource::LoadIcon
//
///////////////////////////////////////
TQPixmap resource::LoadIcon( TQString Name, int Group )
{
	return Icons->loadIcon( Name, (TDEIcon::Group)Group );
}
///////////////////////////////////////
//
//	resource::encryptStr
//
///////////////////////////////////////
//	Borrowed from KMail
TQString resource::encryptStr(const TQString &aStr) const
{
	unsigned int i, val;
	unsigned int len = aStr.length();
	TQCString result;
	result.resize(len+1);
	for (i=0; i<len; i++)
	{
		val = aStr[i] - ' ';
		val = (255-' ') - val;
		result[i] = (char)(val + ' ');
	}
	result[i] = '\0';

	return result;
}
///////////////////////////////////////
//
//	resource::decryptStr
//
///////////////////////////////////////
//	Borrowed from KMail
TQString resource::decryptStr(const TQString &aStr) const
{
	return encryptStr(aStr);
}
///////////////////////////////////////
//
//	resource::play
//
///////////////////////////////////////
void resource::play( const char snd )
{
	Audio->play( snd );
}
///////////////////////////////////////
//
//	resource::ReadColors
//
///////////////////////////////////////
void resource::ReadColors( void )
{
	TQColor tmp;
	
	COLOR_White = TQColor( 255, 255, 255 );
	COLOR_Black = TQColor( 0, 0, 0 );
	CFG->setGroup( "Colors" );
	COLOR_Background = CFG->readColorEntry( "BackgroundColor", &COLOR_White );
	COLOR_GraphBackground = CFG->readColorEntry( "GraphBackground", &COLOR_Background );
	COLOR_Standard = CFG->readColorEntry( "StandardColor", &COLOR_Black );
	COLOR_GraphForeground = CFG->readColorEntry( "GraphForeground", &COLOR_Standard );
	tmp = TQColor( 128, 0, 128 );	// Purple
	COLOR_PrivateTell = CFG->readColorEntry( "PrivateColor", &tmp );
	tmp = TQColor( 0, 0, 160 );	// Blue
	COLOR_ChannelTell = CFG->readColorEntry( "ChannelColor", &tmp );
	tmp = TQColor( 160, 0, 0 );	// Red
	COLOR_Shout = CFG->readColorEntry( "ShoutColor", &tmp );
	tmp = TQColor( 0, 160, 0 );	// Green
	COLOR_Whisper = CFG->readColorEntry( "WhisperColor", &tmp );
	tmp = TQColor( 0, 128, 128 );	// Cyan
	COLOR_Notification = CFG->readColorEntry( "NotificationColor", &tmp );
}
///////////////////////////////////////
//
//	resource::WriteColors
//
///////////////////////////////////////
void resource::WriteColors( void )
{
	CFG->setGroup( "Colors" );
	CFG->writeEntry( "BackgroundColor", COLOR_Background );
	CFG->writeEntry( "StandardColor", COLOR_Standard );
	CFG->writeEntry( "PrivateColor", COLOR_PrivateTell );
	CFG->writeEntry( "ChannelColor", COLOR_ChannelTell );
	CFG->writeEntry( "ShoutColor", COLOR_Shout );
	CFG->writeEntry( "WhisperColor", COLOR_Whisper );
	CFG->writeEntry( "NotificationColor", COLOR_Notification );
	CFG->writeEntry( "GraphForeground", COLOR_GraphForeground );
	CFG->writeEntry( "GraphBackground", COLOR_GraphBackground );
}
///////////////////////////////////////
//
//	resource::ReadFonts
//
///////////////////////////////////////
void resource::ReadFonts( void )
{
	TQFont Fixed = TDEGlobalSettings::fixedFont();
	CFG->setGroup( "Fonts" );
	FONT_Standard = CFG->readFontEntry( "StandardFont", &Fixed );
	FONT_PrivateTell = CFG->readFontEntry( "PrivateFont", &Fixed );
	FONT_ChannelTell = CFG->readFontEntry( "ChannelFont", &Fixed );
	FONT_Shout = CFG->readFontEntry( "ShoutFont", &Fixed );
	FONT_Whisper = CFG->readFontEntry( "WhisperFont", &Fixed );
	FONT_Notification = CFG->readFontEntry( "NotificationFont", &Fixed );
}
///////////////////////////////////////
//
//	resource::WriteFonts
//
///////////////////////////////////////
void resource::WriteFonts( void )
{
	CFG->setGroup( "Fonts" );
	CFG->writeEntry( "StandardFont", FONT_Standard );
	CFG->writeEntry( "PrivateFont", FONT_PrivateTell );
	CFG->writeEntry( "ChannelFont", FONT_ChannelTell );
	CFG->writeEntry( "ShoutFont", FONT_Shout );
	CFG->writeEntry( "WhisperFont", FONT_Whisper );
	CFG->writeEntry( "NotificationFont", FONT_Notification );
}
///////////////////////////////////////
//
//	resource::buildStyle
//
///////////////////////////////////////
void resource::buildStyle( void )
{
	/* Configure SSI_Default */
	SSI_Default->setDisplayMode( TQStyleSheetItem::DisplayListItem );
	SSI_Default->setWhiteSpaceMode( TQStyleSheetItem::WhiteSpacePre );
	SSI_Default->setFontFamily( FONT_Standard.family() );
	SSI_Default->setFontSize( FONT_Standard.pointSize() );
	SSI_Default->setFontUnderline( FONT_Standard.underline() );
	SSI_Default->setFontItalic( FONT_Standard.italic() );
	SSI_Default->setFontWeight( FONT_Standard.weight() );
	SSI_Default->setColor( COLOR_Standard );
	/* Configure SSI_PrivateTell */
	SSI_PrivateTell->setDisplayMode( TQStyleSheetItem::DisplayListItem );
	SSI_PrivateTell->setWhiteSpaceMode( TQStyleSheetItem::WhiteSpacePre );
	SSI_PrivateTell->setFontFamily( FONT_PrivateTell.family() );
	SSI_PrivateTell->setFontSize( FONT_PrivateTell.pointSize() );
	SSI_PrivateTell->setFontUnderline( FONT_PrivateTell.underline() );
	SSI_PrivateTell->setFontItalic( FONT_PrivateTell.italic() );
	SSI_PrivateTell->setFontWeight( FONT_PrivateTell.weight() );
	SSI_PrivateTell->setColor( COLOR_PrivateTell );
	/* Configure SSI_ChannelTell */
	SSI_ChannelTell->setDisplayMode( TQStyleSheetItem::DisplayListItem );
	SSI_ChannelTell->setWhiteSpaceMode( TQStyleSheetItem::WhiteSpacePre );
	SSI_ChannelTell->setFontFamily( FONT_ChannelTell.family() );
	SSI_ChannelTell->setFontSize( FONT_ChannelTell.pointSize() );
	SSI_ChannelTell->setFontUnderline( FONT_ChannelTell.underline() );
	SSI_ChannelTell->setFontItalic( FONT_ChannelTell.italic() );
	SSI_ChannelTell->setFontWeight( FONT_ChannelTell.weight() );
	SSI_ChannelTell->setColor( COLOR_ChannelTell );
	/* Configure SSI_Shout */
	SSI_Shout->setDisplayMode( TQStyleSheetItem::DisplayListItem );
	SSI_Shout->setWhiteSpaceMode( TQStyleSheetItem::WhiteSpacePre );
	SSI_Shout->setFontFamily( FONT_Shout.family() );
	SSI_Shout->setFontSize( FONT_Shout.pointSize() );
	SSI_Shout->setFontUnderline( FONT_Shout.underline() );
	SSI_Shout->setFontItalic( FONT_Shout.italic() );
	SSI_Shout->setFontWeight( FONT_Shout.weight() );
	SSI_Shout->setColor( COLOR_Shout );
	/* Configure SSI_Whisper */
	SSI_Whisper->setDisplayMode( TQStyleSheetItem::DisplayListItem );
	SSI_Whisper->setWhiteSpaceMode( TQStyleSheetItem::WhiteSpacePre );
	SSI_Whisper->setFontFamily( FONT_Whisper.family() );
	SSI_Whisper->setFontSize( FONT_Whisper.pointSize() );
	SSI_Whisper->setFontUnderline( FONT_Whisper.underline() );
	SSI_Whisper->setFontItalic( FONT_Whisper.italic() );
	SSI_Whisper->setFontWeight( FONT_Whisper.weight() );
	SSI_Whisper->setColor( COLOR_Whisper );
	/* Configure SSI_Notification */
	SSI_Notification->setDisplayMode( TQStyleSheetItem::DisplayListItem );
	SSI_Notification->setWhiteSpaceMode( TQStyleSheetItem::WhiteSpacePre );
	SSI_Notification->setFontFamily( FONT_Notification.family() );
	SSI_Notification->setFontSize( FONT_Notification.pointSize() );
	SSI_Notification->setFontUnderline( FONT_Notification.underline() );
	SSI_Notification->setFontItalic( FONT_Notification.italic() );
	SSI_Notification->setFontWeight( FONT_Notification.weight() );
	SSI_Notification->setColor( COLOR_Notification );
}
///////////////////////////////////////
//
//	resource::themeURL
//
///////////////////////////////////////
TQString resource::themeURL( const TQString theme )
{
	TQString fullURL;
	fullURL = "tar:" + GlobalDataDir + "themes/" + theme;
	if( !TDEIO::NetAccess::exists( fullURL ) )
	{
		fullURL = "tar:" + TQDir::currentDirPath() + "../media/" + theme;
		if( !TDEIO::NetAccess::exists( fullURL ) )
		{
			fullURL = "tar:" + TQDir::homeDirPath() + "/.knights/" + theme;
			if( !TDEIO::NetAccess::exists( fullURL ) )
			{
				kdWarning() << "The theme " << theme << " does not exist in any valid path." << endl;
				return TQString();
			}
		}
	}
	fullURL += "/";
	return fullURL;
}

///////////////////////////////////////
//
//	resource::loadSCIDImage
//
///////////////////////////////////////
TQPixmap resource::loadSCIDImage( const TQString &name )
{
	const int BufferMax = 120;
	const int ArrayMax = 21600;
	const int SkipSize = 7200;

	TQPixmap newPix;
	TQString searchName = '\"' + name + '\"';
	TQByteArray base64Data( ArrayMax );
	TQByteArray rawData( ArrayMax );
	char *array = base64Data.data();
	char buffer[BufferMax];
	char photo[12];
	unsigned int index = 0;
	unsigned int buffSize = 0;

	TQString source = locate( "appdata", "players.img" );
	if( source.isNull() )
		source = SCID_Image_Path;

	strcpy( photo, "photo" );
	TQFile file( source );

	if( file.open( IO_ReadOnly ) )
	{
		while( !file.atEnd() )
		{
			file.readLine( buffer, BufferMax );
			if( strstr( buffer, photo ) != NULL )
			{
				if( strstr( buffer, searchName.latin1() ) != NULL )
				{
					/* From here on, we're reading the image */
					index = file.readBlock( array, SkipSize );
					buffer[0] = 0;
					while( ( buffer[0] != '}' ) && ( !file.atEnd() ) )
					{
						memcpy( array + index, buffer, buffSize );
						index += buffSize;
						buffSize = file.readLine( buffer, BufferMax );
					}
					base64Data.truncate( index );
					KCodecs::base64Decode( base64Data, rawData );
					newPix.loadFromData( rawData );
					break;
				}
				else
				{
					file.at( file.at() + SkipSize );
				}
			}
		}
		file.close();
	}
	return newPix;
}

#undef CFG


