/**
 * WHOISCommand.cc
 * Gives varius data about a user
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 * USA.
 *
 * $Id: WHOISCommand.cc,v 1.25 2005/08/24 13:36:32 kewlio Exp $
 */

#include	<string>
#include	<iostream>

#include	<cstdlib>

#include	"Network.h"
#include	"ccontrol.h"
#include	"CControlCommands.h"
#include	"StringTokenizer.h"
#include	"ip.h"
#include	"ccontrol_generic.h"
#include	"gnuworld_config.h"

RCSTAG( "$Id: WHOISCommand.cc,v 1.25 2005/08/24 13:36:32 kewlio Exp $" ) ;

namespace gnuworld
{
using std::endl ;
using std::string ;

namespace uworld
{

// whois nickname
bool WHOISCommand::Exec( iClient* theClient, const string& Message )
{
StringTokenizer st( Message ) ;
if( st.size() < 2 )
	{
	Usage( theClient ) ;
	return true ;
	}

iClient* Target = Network->findNick( st[ 1 ] ) ;
if( NULL == Target )
	{
	bot->Notice( theClient, "Unable to find nick: %s", st[ 1 ].c_str() ) ;
	return true ;
	}
bot->MsgChanLog("WHOIS %s\n",st.assemble(1).c_str());

iServer* targetServer = Network->findServer( Target->getIntYY() ) ;
if( NULL == targetServer )
	{
	elog	<< "WHOISCommand> Unable to find server: "
		<< Target->getIntYY() << endl ;
	return false ;
	}

if((Target->isModeX()) && (Target->isModeR()))
	{
	bot->Notice( theClient, "%s is %s (%s) [%s]",
		st[ 1 ].c_str(),
		Target->getNickUserHost().c_str(),
		Target->getRealNickUserHost().c_str(),
		xIP(Target->getIP() ).GetNumericIP().c_str()
	) ;
	
	}
else	
	{
	bot->Notice( theClient, "%s is %s [%s]",
		st[ 1 ].c_str(),
		Target->getNickUserHost().c_str(),
		xIP(Target->getIP() ).GetNumericIP().c_str()
		) ;
	}

if (Target->getConnectTime() > 0)
{
	/* we have a client connection timestamp, display it */
	bot->Notice(theClient, "%s has been connected for %s [since %ld]",
		st[1].c_str(),
		Ago(Target->getConnectTime()),
		Target->getConnectTime());
}

if (Target->isModeR())
{
	/* client is authed - show it here */
	bot->Notice(theClient, "%s is authed as [%s]",
		st[1].c_str(),
		Target->getAccount().c_str());
}

bot->Notice( theClient, "Numeric: %s, UserModes: %s, Server Numeric: %s (%s)",
	Target->getCharYYXXX().c_str(),
	Target->getStringModes().c_str(),
	targetServer->getCharYY().c_str(),
	targetServer->getName().c_str()
	) ;

if( Target->isOper() )
	{
	bot->Notice( theClient, "%s is an IRCoperator",
		st[ 1 ].c_str() ) ;
	}

if(Target->getMode(iClient::MODE_SERVICES))
	{
	return true;
	}
	
vector< string > channels ;
string curChannel ;
string::size_type curPlace;
string tChannel;
char curChar[10];
gnuworld::Channel* theChannel;
gnuworld::ChannelUser* theChannelUser;
bool hasCC; //Channel has control codes

for( iClient::const_channelIterator ptr = Target->channels_begin() ;
	ptr != Target->channels_end() ; ++ptr )
	{
	curChannel = "";
        theChannel = (*ptr);
        theChannelUser = theChannel->findUser(Target);
        tChannel = theChannel->getName();
        string chanUserModes = string();
        if(theChannelUser->getMode(gnuworld::ChannelUser::MODE_V)) chanUserModes = "+";
        if(theChannelUser->getMode(gnuworld::ChannelUser::MODE_H)) chanUserModes += "%";
        if(theChannelUser->getMode(gnuworld::ChannelUser::MODE_O)) chanUserModes += "@";
        tChannel = chanUserModes + tChannel;

	hasCC = false;
	for(curPlace = 0; curPlace < tChannel.size();++curPlace)
		{
		if(((tChannel[curPlace] > 1) && (tChannel[curPlace] < 4))
			|| (tChannel[curPlace] == 15) 
			|| ((tChannel[curPlace] > 27) && (tChannel[curPlace] < 33))
			|| (tChannel[curPlace] == 22)
			|| (tChannel[curPlace] == char(160))
                        || ((unsigned(tChannel[curPlace]) > 252)  
			&& (unsigned(tChannel[curPlace]) <= 254)))
			{			
			hasCC = true;
			sprintf(curChar,"%d",tChannel[curPlace]);
			curChannel += string("\x16^") + curChar + string("\x16");
			}
		else
			{
			curChannel += tChannel[curPlace];
			}
		}

	if(hasCC)
		{
		curChannel = string("*") + curChannel;
		}

	channels.push_back( curChannel) ;
	}

if( channels.empty() )
	{
	return true ;
	}

string chanNames ;
for( vector< string >::size_type i = 0 ; i < channels.size() ; i++ )
	{
	if ((chanNames.size() + channels[i].size()) > 410)
	{
		/* need to split lines up */
		bot->Notice(theClient, "On channels: %s", chanNames.c_str());
		chanNames = "";
	}
	chanNames += channels[ i ] ;
	if( (i + 1) < channels.size() )
		{
		chanNames += ", " ;
		}
	}

bot->Notice( theClient, "On channels: %s", chanNames.c_str() ) ;
bot->Notice( theClient, "* - Channel contains control codes" );

return true ;
}

}
}

