// ==============================================================
//	This file is part of MegaGlest Shared Library (www.glest.org)
//
//	Copyright (C) 2009-2010 Titus Tscharntke (info@titusgames.de) and
//                          Mark Vejvoda (mark_vejvoda@hotmail.com)
//
//	You can redistribute this code 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 "ircclient.h"
#include "util.h"
#include "platform_common.h"
#include "socket.h"
#include "cache_manager.h"

#if !defined(DISABLE_IRCCLIENT)

#include <libircclient.h>
// upstream moved some defines into new headers as of 1.6
#ifndef LIBIRCCLIENT_PRE1_6
#include <libirc_rfcnumeric.h>
#endif

#endif

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include "conversion.h"

using namespace Shared::Util;
using namespace Shared::PlatformCommon;

namespace Shared { namespace PlatformCommon {

const char *IRCThread::globalCacheContainerName = NULL;
const int IRC_SERVER_PORT = 6667;
//bool IRCThread::debugEnabled = true;
bool IRCThread::debugEnabled = false;

#if !defined(DISABLE_IRCCLIENT)
void addlog (const char * fmt, ...) {
	//FILE * fp;
	char buf[8096];
	va_list va_alist;

	va_start (va_alist, fmt);
#if defined (WIN32)
	_vsnprintf (buf, sizeof(buf), fmt, va_alist);
#else
	vsnprintf (buf, sizeof(buf), fmt, va_alist);
#endif
	va_end (va_alist);

	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: %s\n", buf);

    //if(SystemFlags::VERBOSE_MODE_ENABLED == true) {
    //    if ( (fp = fopen ("irctest.log", "ab")) != 0 ) {
    //        fprintf (fp, "%s\n", buf);
    //        fclose (fp);
    //    }
    //}
}

void dump_event (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {
	char buf[512]="";
	unsigned int cnt=0;
	buf[0] = '\0';

	for ( cnt = 0; cnt < count; cnt++ )	{
		if ( cnt ) {
			strcat (buf, "|");
        }
#ifdef WIN32
		strncat (buf, params[cnt],min((int)strlen(params[cnt]),511));
#else
		strncat (buf, params[cnt],std::min((int)strlen(params[cnt]),511));
#endif
	}

	addlog ("Event \"%s\", origin: \"%s\", params: %d [%s]", event, origin ? origin : "NULL", cnt, buf);

    IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
	if(ctx != NULL) {
		if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
		if(ctx->getQuitStatus()) {
			if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
			return;
		}
		if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
        if(difftime(time(NULL),ctx->getLastNickListUpdate()) >= 7) {
        	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
            ctx->setLastNickListUpdate(time(NULL));
            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
            ctx->GetIRCConnectedNickList(ctx->getChannel(),false);
        }
        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
	}
}

void get_nickname(const char *sourceNick,char *destNick,size_t maxDestBufferSize) {
	string sourceNickStr = sourceNick;
	if(sourceNickStr != "" && sourceNickStr[0] == '@') {
		sourceNickStr.erase(0,1);
	}

	irc_target_get_nick(sourceNickStr.c_str(),destNick,maxDestBufferSize);
}

void event_notice (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {
	dump_event (session, event, origin, params, count);

	if(origin == NULL) {
		return;
	}

	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf("NOTICE from '%s': %s", origin, params[1]);

	//if(strcasecmp (origin, "nickserv")) {
	//	return;
	//}

	if(strstr (params[1], "This nick is not registered") == params[1]) {
		//std::string regcmd = "REGISTER " + gCfg.irc_nickserv_pass + " NOMAIL";
		//gLog.Add (CLog::INFO, "Registering our nick with NICKSERV");
		//irc_cmd_msg (session, "nickserv", regcmd.c_str());
	}
	else if(strstr (params[1], "This nickname is registered and protected") == params[1]) {
		//std::string identcmd = "IDENTIFY " + gCfg.irc_nickserv_pass;
		//gLog.Add (CLog::INFO, "Identifying our nick with NICKSERV");
		//irc_cmd_msg (session, "nickserv", identcmd.c_str());

//	    IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
//		if(ctx != NULL) {
//			if(ctx->getExecute_cmd_onconnect() != "") {
//				irc_cmd_msg(session, "nickserv",  ctx->getExecute_cmd_onconnect().c_str());
//			}
//		}
	}
	else if(strstr (params[1], "Password accepted - you are now recognized") == params[1]) {
		if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf("Nickserv authentication succeed.");
	}
}

void event_join(irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {

	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

	dump_event (session, event, origin, params, count);

	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

    IRCThread *ctx = (IRCThread *)irc_get_ctx(session);

    if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

	if(ctx != NULL) {

		if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

        if(ctx->getHasJoinedChannel() == false) {

        	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

            irc_cmd_user_mode (session, "+i");

            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

            //irc_cmd_msg (session, params[0], "MG Bot says hello!");
            ctx->setHasJoinedChannel(true);

            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

            //ctx->GetIRCConnectedNickList(ctx->getChannel(),true);
            ctx->GetIRCConnectedNickList(ctx->getChannel(),false);

            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
        }
        else {
        	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

            char realNick[128]="";
            get_nickname(origin,realNick,127);
            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: user joined channel realNick [%s] origin [%s]\n", realNick,origin);

            bool foundNick = false;

            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

            MutexSafeWrapper safeMutex(ctx->getMutexNickList(),string(__FILE__) + "_" + intToStr(__LINE__));
            std::vector<string> nickList = ctx->getCachedNickList();
            for(unsigned int i = 0;
                             i < nickList.size(); ++i) {
                if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: looking for match [%s] realNick [%s]\n", nickList[i].c_str(),realNick);

                if(nickList[i] == realNick) {
                    foundNick = true;
                    break;
                }
            }
            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

            if(foundNick == false) {
                nickList.push_back(realNick);
            }

            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
        }

        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

        if(ctx->getWantToLeaveChannel() == true) {
        	ctx->leaveChannel();
        }

        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
    }
}

void event_connect (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {
    IRCThread *ctx = (IRCThread *)irc_get_ctx(session);

	dump_event(session, event, origin, params, count);

	//IRC: Event "433", origin: "leguin.freenode.net", params: 3 [*|softcoder|Nickname is already in use.]
//	printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
//	if(strstr (params[1], "Nickname is already in use") == params[1]) {
//		IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
//		if(ctx != NULL) {
//			if(ctx->getExecute_cmd_onconnect() != "") {
//				irc_cmd_msg(session, "nickserv",  ctx->getExecute_cmd_onconnect().c_str());
//			}
//		}
//	}
//	else
	if(ctx != NULL) {
        irc_cmd_join(session, ctx->getChannel().c_str(), 0);
    }
}

void event_privmsg (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {
	dump_event (session, event, origin, params, count);

	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("'%s' said me (%s): %s\n",origin ? origin : "someone",params[0], params[1] );
}

void dcc_recv_callback (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length) {

	switch (status)
	{
	case LIBIRC_ERR_CLOSED:
		if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC %d: chat closed\n", id);
		break;

	case 0:
		if ( !data ) {
			if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC %d: chat connected\n", id);
			irc_dcc_msg	(session, id, "Hehe");
		}
		else {
			if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC %d: %s\n", id, data);

			static int count = 1;
			char buf[12]="";
			sprintf (buf, "DCC [%d]: %d", id, count++);
			irc_dcc_msg	(session, id, buf);
		}
		break;

	default:
		if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC %d: error %s\n", id, irc_strerror(status));
		break;
	}
}

void dcc_file_recv_callback (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length) {
	if ( status == 0 && length == 0 ) {
		if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("File sent successfully\n");

		if ( ctx ) {
			fclose ((FILE*) ctx);
		}
	}
	else if ( status ) {
		if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("File sent error: %d\n", status);

		if ( ctx ) {
			fclose ((FILE*) ctx);
		}
	}
	else {
		if ( ctx ) {
			fwrite (data, 1, length, (FILE*) ctx);
		}
		if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("File sent progress: %u\n", length);
	}
}

void event_channel(irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {
	//IRC: Event "433", origin: "leguin.freenode.net", params: 3 [*|softcoder|Nickname is already in use.]
	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf("In [%s::%s] Line: %d count = %u origin = %s\n",__FILE__,__FUNCTION__,__LINE__,count,(origin ? origin : "null"));

	if ( count != 2 )
		return;

	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: '%s' said in channel %s: %s\n",origin ? origin : "someone",params[0], params[1] );

	if ( !origin ) {
		return;
	}

    char realNick[128]="";
    get_nickname(origin,realNick,127);
    if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: event signalled realNick [%s] origin [%s]\n", realNick,origin);

    IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
	if(ctx != NULL) {
        MutexSafeWrapper safeMutex(ctx->getMutexIRCCB(),string(__FILE__) + "_" + intToStr(__LINE__));
        IRCCallbackInterface *cb = ctx->getCallbackObj(false);
        if(cb != NULL) {
            cb->IRC_CallbackEvent(IRC_evt_chatText, realNick, params, count);
        }
	}

//	if ( !strcmp (params[1], "quit") )
//		irc_cmd_quit (session, "of course, Master!");
//
//	if ( !strcmp (params[1], "help") ) {
//		irc_cmd_msg (session, params[0], "quit, help, dcc chat, dcc send, ctcp");
//	}
//
//	if ( !strcmp (params[1], "ctcp") ) {
//		irc_cmd_ctcp_request (session, realNick, "PING 223");
//		irc_cmd_ctcp_request (session, realNick, "FINGER");
//		irc_cmd_ctcp_request (session, realNick, "VERSION");
//		irc_cmd_ctcp_request (session, realNick, "TIME");
//	}
//
//	if ( !strcmp (params[1], "dcc chat") ) {
//		irc_dcc_t dccid;
//		irc_dcc_chat (session, 0, realNick, dcc_recv_callback, &dccid);
//		if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC chat ID: %d\n", dccid);
//	}
//
//	if ( !strcmp (params[1], "dcc send") ) {
//		irc_dcc_t dccid;
//		irc_dcc_sendfile (session, 0, realNick, "irctest.c", dcc_file_recv_callback, &dccid);
//		if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC send ID: %d\n", dccid);
//	}
//
//	if ( !strcmp (params[1], "topic") ) {
//		irc_cmd_topic (session, params[0], 0);
//    }
//	else if ( strstr (params[1], "topic ") == params[1] ) {
//		irc_cmd_topic (session, params[0], params[1] + 6);
//    }
//
//	if ( strstr (params[1], "mode ") == params[1] )
//		irc_cmd_channel_mode (session, params[0], params[1] + 5);
//
//	if ( strstr (params[1], "nick ") == params[1] )
//		irc_cmd_nick (session, params[1] + 5);
//
//	if ( strstr (params[1], "whois ") == params[1] )
//		irc_cmd_whois (session, params[1] + 5);
}

void irc_event_dcc_chat(irc_session_t * session, const char * nick, const char * addr, irc_dcc_t dccid) {
	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC chat [%d] requested from '%s' (%s)\n", dccid, nick, addr);

	irc_dcc_accept (session, dccid, 0, dcc_recv_callback);
}

void irc_event_dcc_send(irc_session_t * session, const char * nick, const char * addr, const char * filename, unsigned long size, irc_dcc_t dccid) {
	FILE * fp;
	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC send [%d] requested from '%s' (%s): %s (%lu bytes)\n", dccid, nick, addr, filename, size);

	if ( (fp = fopen ("file", "wb")) == 0 ) {
		abort();
	}
	irc_dcc_accept (session, dccid, fp, dcc_file_recv_callback);
}

void event_leave(irc_session_t *session, const char *event, const char *origin, const char ** params, unsigned count) {
	char buf[24]="";
	sprintf (buf, "%s", event);

	// someone left the channel.
	if(origin) {
	    if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: user left channel [%s]\n", origin);

        char realNick[128]="";
        get_nickname(origin,realNick,127);
        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: user left channel realNick [%s] origin [%s]\n", realNick,origin);

        IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
        if(ctx != NULL) {
            MutexSafeWrapper safeMutex(ctx->getMutexNickList(),string(__FILE__) + "_" + intToStr(__LINE__));
            std::vector<string> &nickList = ctx->getCachedNickList();
            for(unsigned int i = 0;
                             i < nickList.size(); ++i) {
                if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: lookingfor match [%s] realNick [%s]\n", nickList[i].c_str(),realNick);

                if(nickList[i] == realNick) {
                    nickList.erase(nickList.begin() + i);
                    break;
                }
            }
        }
	}

	dump_event (session, buf, origin, params, count);
}
void event_numeric(irc_session_t * session, unsigned int event, const char * origin, const char ** params, unsigned int count) {
	char buf[24]="";
	sprintf (buf, "%u", event);

	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d event = %u\n", __LINE__, event);

    switch (event) {
		case LIBIRC_RFC_ERR_NICKNAMEINUSE :
		case LIBIRC_RFC_ERR_NICKCOLLISION :
			//irc_auto_rename_nick(session);
			//IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
			//if(ctx != NULL) {
//			{
//			//IRC: Event "433", origin: "leguin.freenode.net", params: 3 [*|softcoder|Nickname is already in use.]
//			printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
//			//if(strstr (params[1], "Nickname is already in use") == params[1]) {
//				IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
//				if(ctx != NULL) {
//					if(ctx->getExecute_cmd_onconnect() != "") {
//						irc_cmd_msg(session, "nickserv",  ctx->getExecute_cmd_onconnect().c_str());
//					}
//				}
//			//}
//			}
			break;

		case LIBIRC_RFC_ERR_NOTREGISTERED :
			//irc_auto_rename_nick(session);
			//IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
			//if(ctx != NULL) {
//			{
			//===> IRC: Event "451", origin: "leguin.freenode.net", params: 2 [*|You have not registered]
//			printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
//			//if(strstr (params[1], "Nickname is already in use") == params[1]) {
//				IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
//				if(ctx != NULL) {
//					//if(ctx->getExecute_cmd_onconnect() != "") {
//						//irc_cmd_msg(session, "nickserv",  ctx->getExecute_cmd_onconnect().c_str());
//						string cmd = "REGISTER " + ctx->getNick() + " NOMAIL";
//						irc_cmd_msg (session, "nickserv", cmd.c_str());
//					//}
//				}
//			//}
//			}
			break;

		case LIBIRC_RFC_RPL_TOPIC :
			break;
		case LIBIRC_RFC_RPL_NAMREPLY :
            {
                if(event == LIBIRC_RFC_RPL_NAMREPLY) {

                	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: LIBIRC_RFC_RPL_NAMREPLY count = %u\n", count);

                    std::vector<string> nickList;
                    if(count >= 4) {
                        for(unsigned int i = 3; i < count && params[i]; ++i) {
                            vector<string> tokens;
                            Tokenize(params[i],tokens," ");

                            for(unsigned int j = 0; j < tokens.size(); ++j) {

                                char realNick[128]="";
                                get_nickname(tokens[j].c_str(),realNick,127);
                                if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: LIBIRC_RFC_RPL_NAMREPLY user joined channel realNick [%s] tokens[j] [%s]\n", realNick,tokens[j].c_str());

                                // Only show MegaGlest users in the user list
                                //if(strncmp(&realNick[0],"MG_",3) == 0) {
                                nickList.push_back(realNick);
                                //}
                            }
                        }
                    }

                    IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
                    if(ctx != NULL) {
                        MutexSafeWrapper safeMutex(ctx->getMutexNickList(),string(__FILE__) + "_" + intToStr(__LINE__));
                        ctx->setCachedNickList(nickList);
                    }
                }
                break;
            }
        case LIBIRC_RFC_RPL_ENDOFNAMES:
            {
            	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("!!!!! ===> IRC: Line: %d event = %u\n", __LINE__, event);

                IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
                if(ctx != NULL) {
                	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d event = %u\n", __LINE__, event);

                    ctx->setEventDataDone(true);
                }
                if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d event = %u\n", __LINE__, event);
            }
            break;
    }

	dump_event (session, buf, origin, params, count);
}

#endif

bool IRCThread::getEventDataDone() {
	MutexSafeWrapper safeMutex(&mutexEventDataDone,string(__FILE__) + "_" + intToStr(__LINE__));
	bool result = eventDataDone;
	safeMutex.ReleaseLock();

	return result;
}
void IRCThread::setEventDataDone(bool value) {
	MutexSafeWrapper safeMutex(&mutexEventDataDone,string(__FILE__) + "_" + intToStr(__LINE__));
	eventDataDone=value;
}

IRCThread::IRCThread(const std::vector<string> &argv, IRCCallbackInterface *callbackObj) : BaseThread() {
	uniqueID = "IRCThread";
    this->argv = argv;
    this->callbackObj = callbackObj;
    ircSession = NULL;
    eventData.clear();
    setEventDataDone(false);
    hasJoinedChannel = false;
    lastNickListUpdate = time(NULL);
    wantToLeaveChannel = false;
    playerName = "";
}

void IRCThread::disconnect() {
#if !defined(DISABLE_IRCCLIENT)

	MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
	bool validSession = (ircSession != NULL);
	safeMutex.ReleaseLock();

    if(validSession == true) {
        setCallbackObj(NULL);
        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Quitting Channel\n");

        MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
        if(ircSession != NULL) {
        	irc_disconnect(ircSession);
        }
        safeMutex1.ReleaseLock();

        BaseThread::signalQuit();
        hasJoinedChannel = false;
    }
#else
    BaseThread::signalQuit();
#endif
}

void IRCThread::signalQuit() {
    if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: signalQuit [%p]\n",ircSession);

#if !defined(DISABLE_IRCCLIENT)

	MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
	bool validSession = (ircSession != NULL);
	safeMutex.ReleaseLock();

    if(validSession == true) {
        setCallbackObj(NULL);
        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Quitting Channel\n");

        MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
        if(ircSession != NULL) {
        	irc_cmd_quit(ircSession, "MG Bot is closing!");
        }
        safeMutex1.ReleaseLock();
		hasJoinedChannel = false;
    }
    BaseThread::signalQuit();

#else
    BaseThread::signalQuit();
#endif
}

bool IRCThread::shutdownAndWait() {
    if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: shutdownAndWait [%p]\n",ircSession);

    signalQuit();
    return BaseThread::shutdownAndWait();
}

void IRCThread::SendIRCCmdMessage(string target, string msg) {
	MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
	bool validSession = (ircSession != NULL);
	safeMutex.ReleaseLock();

    if(validSession == true && hasJoinedChannel == true) {
    	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] sending IRC command to [%s] cmd [%s]\n",__FILE__,__FUNCTION__,__LINE__,target.c_str(),msg.c_str());

#if !defined(DISABLE_IRCCLIENT)
    	MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
    	int ret = 0;
    	if(ircSession != NULL) {
    		ret = irc_cmd_msg (ircSession, target.c_str(), msg.c_str());
    	}
        safeMutex1.ReleaseLock();

        if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] sending IRC command to [%s] cmd [%s] ret = %d\n",__FILE__,__FUNCTION__,__LINE__,target.c_str(),msg.c_str(),ret);
#endif
    }
}

std::vector<string> IRCThread::GetIRCConnectedNickList(string target, bool waitForCompletion) {
    setEventDataDone(false);

    if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
	MutexSafeWrapper safeMutexSession(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
	bool validSession = (ircSession != NULL);
	safeMutexSession.ReleaseLock();

	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

    if(validSession == true && hasJoinedChannel == true) {
    	if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] sending IRC nick list command to [%s]\n",__FILE__,__FUNCTION__,__LINE__,target.c_str());

#if !defined(DISABLE_IRCCLIENT)

    	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

    	MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));

    	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
        int ret = irc_cmd_names (ircSession, target.c_str());
        safeMutex1.ReleaseLock();

        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
        if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] sending IRC nick list command to [%s] ret = %d\n",__FILE__,__FUNCTION__,__LINE__,target.c_str(),ret);

        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

        if(waitForCompletion == true) {

        	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

            for(time_t tElapsed = time(NULL);
                getEventDataDone() == false &&
                this->getQuitStatus() == false &&
                difftime(time(NULL),tElapsed) <= 5;) {
                sleep(50);
            }

            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
        }

        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
#endif
    }

    if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

    MutexSafeWrapper safeMutex(&mutexNickList,string(__FILE__) + "_" + intToStr(__LINE__));
    std::vector<string> nickList = eventData;
    safeMutex.ReleaseLock();

    if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

    return nickList;
}

bool IRCThread::isConnected(bool mutexLockRequired) {
    bool ret = false;
    if(this->getQuitStatus() == false) {
		MutexSafeWrapper safeMutex(NULL,string(__FILE__) + "_" + intToStr(__LINE__));
		int lockStatus = 0;
		if(mutexLockRequired == true) {
			lockStatus = safeMutex.setMutexAndTryLock(&mutexIRCSession);
		}
		bool validSession = (lockStatus == SDL_MUTEX_TIMEDOUT || (lockStatus == 0 && ircSession != NULL));
		if(mutexLockRequired == true && lockStatus == 0) {
			safeMutex.ReleaseLock();
		}

		if(validSession == true) {
#if !defined(DISABLE_IRCCLIENT)
			MutexSafeWrapper safeMutex1(NULL,string(__FILE__) + "_" + intToStr(__LINE__));
			if(ircSession != NULL) {
				lockStatus = 0;
				if(mutexLockRequired == true) {
					lockStatus = safeMutex1.setMutexAndTryLock(&mutexIRCSession);
				}
				ret = (lockStatus == SDL_MUTEX_TIMEDOUT || (lockStatus == 0 && irc_is_connected(ircSession) != 0));
			}
			if(mutexLockRequired == true && lockStatus == 0) {
				safeMutex1.ReleaseLock();
			}
		}
#endif
    }

    return ret;
}

std::vector<string> IRCThread::getNickList() {
    MutexSafeWrapper safeMutex(&mutexNickList,string(__FILE__) + "_" + intToStr(__LINE__));
    std::vector<string> nickList = eventData;
    safeMutex.ReleaseLock();

    return nickList;
}

IRCCallbackInterface * IRCThread::getCallbackObj(bool lockObj) {
    MutexSafeWrapper safeMutex(NULL,string(__FILE__) + "_" + intToStr(__LINE__));
    if(lockObj == true) {
        safeMutex.setMutex(&mutexIRCCB);
    }
    return callbackObj;
}
void IRCThread::setCallbackObj(IRCCallbackInterface *cb) {
    MutexSafeWrapper safeMutex(&mutexIRCCB,string(__FILE__) + "_" + intToStr(__LINE__));
    callbackObj=cb;
}

void IRCThread::execute() {
    {
        RunningStatusSafeWrapper runningStatus(this);
        if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] argv.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,argv.size());
        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: IRCThread::execute Line: %d\n", __LINE__);

        if(getQuitStatus() == true) {
        	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
            return;
        }

        if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"IRC thread is running\n");
        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

        try	{
#if !defined(DISABLE_IRCCLIENT)
            irc_callbacks_t	callbacks;

        	MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
        	ircSession=NULL;
        	safeMutex.ReleaseLock(true);

            if(argv.size() != 5) {
                if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC Usage: <server> <nick> <channel> : got params [%ld]\n",(long int)argv.size());
                return;
            }

            memset (&callbacks, 0, sizeof(callbacks));

            callbacks.event_connect = event_connect;
            callbacks.event_join = event_join;
            callbacks.event_nick = dump_event;
            callbacks.event_quit = dump_event;
            callbacks.event_part = event_leave;
            callbacks.event_mode = dump_event;
            callbacks.event_topic = dump_event;
            callbacks.event_kick = dump_event;
            callbacks.event_channel = event_channel;
            callbacks.event_privmsg = event_privmsg;
            callbacks.event_notice = event_notice;
            callbacks.event_invite = dump_event;
            callbacks.event_umode = dump_event;
            callbacks.event_ctcp_rep = dump_event;
            callbacks.event_ctcp_action = dump_event;
            callbacks.event_unknown = dump_event;
            callbacks.event_numeric = event_numeric;

            callbacks.event_dcc_chat_req = irc_event_dcc_chat;
            callbacks.event_dcc_send_req = irc_event_dcc_send;

            if(this->getQuitStatus() == true) {
            	if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
                return;
            }
            safeMutex.Lock();
            ircSession = irc_create_session (&callbacks);
        	bool validSession = (ircSession != NULL);

            if(validSession == false) {
            	safeMutex.ReleaseLock();
                if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC Could not create session\n");
                return;
            }
            safeMutex.ReleaseLock(true);

//            this->execute_cmd_onconnect = "";
//            if(argv.size() >= 5) {
//            	this->execute_cmd_onconnect = argv[4]; // /msg NickServ identify <password>.
//            }

//            this->password = "";
//            if(argv.size() >= 5) {
//            	this->password = argv[4];
//            }
            this->username = argv[1];
            if(argv.size() >= 4) {
            	this->username = argv[3];
            }
            this->channel = argv[2];
            this->nick    = argv[1];

            safeMutex.Lock();
            irc_set_ctx(ircSession, this);
            safeMutex.ReleaseLock(true);

            if(this->getQuitStatus() == true) {
                return;
            }

            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

            safeMutex.Lock();
            if(irc_connect(ircSession, argv[0].c_str(), IRC_SERVER_PORT, 0, this->nick.c_str(), this->username.c_str(), "megaglest")) {
            	safeMutex.ReleaseLock();
                if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC Could not connect: %s\n", irc_strerror (irc_errno(ircSession)));
                return;
            }
            safeMutex.ReleaseLock();

            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

            if(this->getQuitStatus() == true) {
                return;
            }

            if(this->getQuitStatus() == true) {
                return;
            }

			//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

            for(int iAttempts=1;
                this->getQuitStatus() == false && iAttempts <= 7; ++iAttempts) {
                //if(irc_run(ircSession)) {

            	int run_result = irc_run_session(ircSession);
            	if(run_result && this->getQuitStatus() == false) {
					//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);

                    if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC Could not run the session: %s run_result = %d\n", irc_strerror (irc_errno(ircSession)), run_result);
                    printf ("===> IRC Could not run the session: %s run_result = %d\n", irc_strerror (irc_errno(ircSession)), run_result);
                }
            }

            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);

			//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
#else
            for(;this->getQuitStatus() == false;) {
            	sleep(50);
            }
#endif
            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC exiting IRC CLient!\n");
			//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
        }
        catch(const exception &ex) {
            SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
            if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
        }
        catch(...) {
            SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] UNKNOWN Error\n",__FILE__,__FUNCTION__,__LINE__);
            if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__);
        }

        if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] IRC thread is exiting\n",__FILE__,__FUNCTION__,__LINE__);
        if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
		//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);


		//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
		// Delete ourself when the thread is done (no other actions can happen after this
		// such as the mutex which modifies the running status of this method
		MutexSafeWrapper safeMutex(&mutexIRCCB,string(__FILE__) + "_" + intToStr(__LINE__));
		IRCCallbackInterface *cb = getCallbackObj(false);
		if(cb != NULL) {
			//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
			if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
		   cb->IRC_CallbackEvent(IRC_evt_exitThread, NULL, NULL, 0);
		}
		safeMutex.ReleaseLock();

    }
	//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);

    if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In IRCThread() calling delete ...\n");

	//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
	setDeleteAfterExecute(true);
}

int IRCThread::irc_run_session(irc_session_t * session) {
//	if ( session->state != LIBIRC_STATE_CONNECTING )
//	{
//		session->lasterror = LIBIRC_ERR_STATE;
//		return 1;
//	}

	MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));

	if ( isConnected(false) == false ) {
		//session->lasterror = LIBIRC_ERR_STATE;
		return 1;
	}
	safeMutex.ReleaseLock(true);

	bool isSessionConnected = true;
	while ( isSessionConnected == true && this->getQuitStatus() == false) {
		struct timeval tv;
		fd_set in_set, out_set;
		int maxfd = 0;

		tv.tv_usec = 250000;
		tv.tv_sec = 0;

		// Init sets
		FD_ZERO (&in_set);
		FD_ZERO (&out_set);

		safeMutex.Lock();
		irc_add_select_descriptors (session, &in_set, &out_set, &maxfd);
		safeMutex.ReleaseLock(true);

		if ( select (maxfd + 1, &in_set, &out_set, 0, &tv) < 0 ) {
			int lastSocketError = Socket::getLastSocketError();
			if ( lastSocketError == PLATFORM_SOCKET_INTERRUPTED ) {
				continue;
			}

			//session->lasterror = LIBIRC_ERR_TERMINATED;
			return 2;
		}

		safeMutex.Lock();
		if ( irc_process_select_descriptors (session, &in_set, &out_set) ) {
			safeMutex.ReleaseLock();
			return 3;
		}

		isSessionConnected = isConnected(false);
		safeMutex.ReleaseLock(true);
	}

	return 0;
}

IRCThread::~IRCThread() {
	//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);

	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In ~IRCThread() ...\n");

	if(IRCThread::globalCacheContainerName != NULL) {
		//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);

		IRCThread * &ircClient = CacheManager::getCachedItem< IRCThread * >(IRCThread::globalCacheContainerName);
		ircClient = NULL;
	}

	//printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
}

void normalizeNick(char *nick) {
	// http://tools.ietf.org/html/rfc1459#section-2.3.1
//	<target>     ::= <to> [ "," <target> ]
//	   <to>         ::= <channel> | <user> '@' <servername> | <nick> | <mask>
//	   <channel>    ::= ('#' | '&') <chstring>
//	   <servername> ::= <host>
//	   <host>       ::= see RFC 952 [DNS:4] for details on allowed hostnames
//	   <nick>       ::= <letter> { <letter> | <number> | <special> }
//	   <mask>       ::= ('#' | '$') <chstring>
//	   <chstring>   ::= <any 8bit code except SPACE, BELL, NUL, CR, LF and
//	                     comma (',')>
//
//	   Other parameter syntaxes are:
//
//	   <user>       ::= <nonwhite> { <nonwhite> }
//	   <letter>     ::= 'a' ... 'z' | 'A' ... 'Z'
//	   <number>     ::= '0' ... '9'
//	   <special>    ::= '-' | '[' | ']' | '\' | '`' | '^' | '{' | '}'

	if(nick != NULL && strlen(nick) > 0) {
		char *newNick = new char[strlen(nick)+1];
		memset(newNick,0,strlen(nick)+1);
		bool nickChanged = false;

		for(unsigned int i = 0; i < strlen(nick); ++i) {
			if(nick[i] == '-' || nick[i] == '[' || nick[i] == ']' || nick[i] == '_' ||
			   nick[i] == '\\' || nick[i] == '`' || nick[i] == '^' ||
			   nick[i] == '{' || nick[i] == '}' ||
			   (nick[i] >= '0' && nick[i] <= '9') ||
			   (nick[i] >= 'a' && nick[i] <= 'z') ||
			   (nick[i] >= 'A' && nick[i] <= 'Z')) {
				strncat(newNick,&nick[i],1);
			}
			else {
				strcat(newNick,"-");
				nickChanged = true;
			}
		}

		if(nickChanged == true) {
			strcpy(nick,newNick);
		}

		delete [] newNick;
	}
}

void IRCThread::connectToHost() {
	bool connectRequired = false;

	MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
	bool validSession = (ircSession != NULL);
	safeMutex.ReleaseLock();

	if(validSession == false) {
		connectRequired = true;
	}
	else {
#if !defined(DISABLE_IRCCLIENT)

		MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
		int result = irc_is_connected(ircSession);
		if(result != 1) {
			connectRequired = true;
		}
		safeMutex1.ReleaseLock();
#endif
	}

	if(connectRequired == false) {
#if !defined(DISABLE_IRCCLIENT)
		MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
        if(irc_connect(ircSession, argv[0].c_str(), IRC_SERVER_PORT, 0, this->nick.c_str(), this->username.c_str(), "megaglest")) {
        	safeMutex1.ReleaseLock();

            if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC Could not connect: %s\n", irc_strerror (irc_errno(ircSession)));
            return;
        }
        safeMutex1.ReleaseLock();
#endif
	}
}

void IRCThread::joinChannel() {
	wantToLeaveChannel = false;
	connectToHost();

	MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
	bool validSession = (ircSession != NULL);
	safeMutex.ReleaseLock();

	if(validSession == true) {
#if !defined(DISABLE_IRCCLIENT)

		MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
		IRCThread *ctx = (IRCThread *)irc_get_ctx(ircSession);
		if(ctx != NULL) {
			eventData.clear();
			setEventDataDone(false);
			hasJoinedChannel = false;
			lastNickListUpdate = time(NULL);

			irc_cmd_join(ircSession, ctx->getChannel().c_str(), 0);
			safeMutex.ReleaseLock();
		}
		safeMutex.ReleaseLock();
#endif
	}
}

void IRCThread::leaveChannel() {
	wantToLeaveChannel = true;

	MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
	bool validSession = (ircSession != NULL);
	safeMutex.ReleaseLock();

	if(validSession == true) {
#if !defined(DISABLE_IRCCLIENT)

		MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
		IRCThread *ctx = (IRCThread *)irc_get_ctx(ircSession);
		if(ctx != NULL) {
			irc_cmd_part(ircSession,ctx->getChannel().c_str());
			safeMutex.ReleaseLock();
		}
		safeMutex.ReleaseLock();
#endif
	}
}

}}//end namespace
