/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@falcon.mercer.peachnet.edu 
MUD++ development mailing list    mudpp-list@spice.com
------------------------------------------------------------------------------
nanny.cc
*/


#include "string.h"
#include "llist.h"
#include "server.h"
#include "screen.h"
#include "room.h"
#include "pc.h"
#include "indexable.h"

#include "global.h"


// These are at the bottom of file
extern const char * MAIN_MENU;
extern const char * RACE_MENU;
extern const char * CLASS_MENU;
extern const char * DISCLAIMER;

// Handle newly arrived players
// I used the name 'Nanny' just for old time's sake.

bool isConnected( const String & );


bool checkName( const String & str )
{
	if( !str )
		return false;

	int i= 0;
	while( str[i] )
	{
		if( !isalpha( str[i] ) )
			return false;

		i++;
	}

	return true;
}


void Nanny( PC *ch, String & arg )
{
	String str;
	String filename;
	Room * room;

	switch( ch->getState() )
	{
		default:
			return;

		case STATE_INIT:
			ch->out("What shall we call you ? ");
			ch->setState( STATE_GET_NAME );
			return;

		case STATE_GET_NAME:
			arg.toProper();
			if( isConnected( arg ) )
			{
				ch->out( "Already connected.\n\r" );
				return;
			}
				
			if( !checkName( arg ) )
			{
				ch->out( "Illegal name.\n\r" );
				ch->setState( STATE_BOOT );
				return;
			}

			ch->setName( arg );
			filename << PLAYER_DIR << '/' << arg[0] << '/'
				<< arg;
			if( ch->readFrom( filename ) )
			{
				ch->setState( STATE_GET_OLD_PASSWORD );
				ch->out(INVERSE);
				ch->out("Password:");
				ch->out(NTEXT);
				ch->flush();
				ch->getSock()->echoOff();
				return; 
			}
			ch->setState( STATE_CONFIRM_NAME );
			ch->out("Are you sure (y/n)?");
			return;

		case STATE_CONFIRM_NAME:
			switch( arg[0] )
			{
				default:
					ch->setState( STATE_BOOT );
					return;
				case 'y' :
				case 'Y' :
					ch->setShort( ch->getName() );
					str << ch->getName() << " is here.";
					ch->setLong( str );
					ch->setState( STATE_GET_NEW_PASSWORD );
					ch->out("Ok.\n\rGive me a password:");
					ch->getSock()->echoOff();
					return;
				case 'n' :
				case 'N' :
					ch->out("What is it then?");
					ch->setState( STATE_GET_NAME );
					return;
			} 
			return;

		case STATE_GET_NEW_PASSWORD:
			switch( arg[0] )
			{
				default:
					ch->setPasswd( arg.crypt( ch->getName() ) );
					ch->setState( STATE_CONFIRM_PASSWORD );
					ch->out("\n\rAgain:");
					return;
				case '\0': 
					ch->setState( STATE_BOOT );
					return;
			}
			return;

		case STATE_CONFIRM_PASSWORD:
			switch( arg[0] )
			{
				default:
					if( arg.crypt( ch->getName() ) != ch->getPasswd() )
					{
						ch->setState( STATE_GET_NEW_PASSWORD );
						ch->out("\n\rPasswords dont match, try again.\n\rPassword:");
						return;
					}
					ch->getSock()->echoOn();
					ch->setState( STATE_GET_CLASS );
					ch->out("\n\r[ PRESS RETURN ]\n\r" );
					return;
				case '\0':
					ch->setState( STATE_BOOT );
					return;
			}
			return;

		case STATE_GET_OLD_PASSWORD:
			switch( arg[0] )
			{
				default:
					// This is for empty passwd to allow access
					if( ch->getPasswd()
						&&
						arg.crypt( ch->getName() ) != ch->getPasswd() )
					{
						ch->out("\n\rImposter!\n\r");
						ch->setState( STATE_BOOT );
						return;
					}
					ch->getSock()->echoOn();
					ch->setState( STATE_MAIN_MENU );
					ch->out( MAIN_MENU );
					return;
				case '\0':
				case '\n':
					if( !ch->getPasswd() )
					{
						ch->getSock()->echoOn();
						ch->setState( STATE_MAIN_MENU );
						ch->out( MAIN_MENU );
						return;
					}
					else
					{
						ch->setState( STATE_BOOT );
						return;
					}
				return;
			}

		case STATE_MAIN_MENU:
			switch( arg[0] )
			{
				default:
					ch->out( MAIN_MENU );
					return;
				case '0': 
					ch->setState( STATE_BOOT );
					return;
				case '1':
					ch->out("May your stay be fun!\n\n\r" );

					ch->out( DISCLAIMER ); 

					ch->setState( STATE_PLAYING );
					room = lookupRoom( "the-void:0" );
					if( ! room )
					{
						ch->out( "MUD++ server panic. Can't lookup room." );
						ch->setState( STATE_BOOT );
						return;
					}
					room->addCharInv( ch );
					ch->checkMail();
					str << ch->getName() << " has entered the game.\n\r";
					room->outAllCharExcept( str, ch, NULL );
					return;
				case '5':
					ch->view( "../help/wizlist" );
					ch->page( "" );
					return;
			}

		case STATE_GET_CLASS:
			switch( arg[0] )
			{
				default:
					if( isdigit( arg[0] ) )
					{
						if( arg.asInt() > MAX_CLASS)
						{
							ch->out("Invalid class number.\n\r[HIT RETURN]\n\r" );
						}
						else
						{
							ch->setClass( arg.asInt() );
							ch->setState( STATE_MAIN_MENU );
							ch->out("\n\r[ PRESS RETURN ]\n\r" );
						}
						return;
					}
					ch->out( CLASS_MENU );
					return;
				case 'h':
					ch->out( "Sorry, no helps yet.\n\r[HIT RETURN]\n\r" );
					return;
			}
	}
}

bool isConnected( const String & name )
{
	PC *pc;

	LList<PC> tlist = pcs;
	tlist.reset();

	while( ( pc = tlist.peek() ) )
	{
		tlist.next();

		if( pc->isName( name ) )
			return true;
	}

	return false;
}


const char *DISCLAIMER = "\x1B[2J"
"\n\r"
"Attention : This is the development version of MUD++.\n\r"
"            This is original code.\n\r"
"            The game is nowhere near playable but you are\n\r"
"            welcome to experiment, ie. crash the game. When\n\r"
"            you do, please mail me with specifics.\n\r"
"\n\r"
" -Fusion <msmith@falcon.mercer.peachnet.edu>\n\n\n\r";


const char *MAIN_MENU  =  "\x1B[2J"
"\n\r"
"                            |\\|\\  | | |\\   _|_ _|_\n\r"
"                            | | | |_| |_|   |   |  \n\r"
"\n\r"
"                                 (M)ulti\n\r"
"                                 (U)ser\n\r"
"                          /\\     (D)imension\n\r"
"                     /\\ /    \\    +                      /\\     \n\r"
"                   /    \\      \\  +                 /\\ /    \\   \n\r" 
"                 //       \\      \\                //   \\      \\ \n\r"
"               -==============================================-\n\r"
"              |        Welcome to MUD++...                     |\n\r"
"              |-==============================================-|\n\r"
"              |        [1] Enter the game.                     |\n\r"
"              |        [2] Change password.                    |\n\r"
"              |        [3] Delete this character.              |\n\r"
"              |        [4] A little help to get started.       |\n\r"
"              |        [5] List the resident Wizards.          |\n\r"
"              |        [0] Quit.                               |\n\r"
"              |________________________________________________|\n\r"
"                       Select -> ";

const char *CLASS_MENU =  "\x1B[2J"
"-=====================================-\n\r"
" Type help <num> to see stats for class\n\r"
"-=====================================-\n\r"
" [1] Magic User\n\r"
" [2] Cleric\n\r"
" [3] Thief\n\r"
" [4] Warrior\n\r"
" [5] Monk\n\r"
" [6] Pscionicist\n\r"
"-=====================================-\n\r"
" Select a class -> ";

const char *RACE_MENU =   "\x1B[2J"
"-========================================-\n\r"
" Type help <num> to display stats for race\n\r"
"-========================================-\n\r"
" [1] Human\n\r"
" [2] Draconian  (cold blooded)\n\r"
" [3] Atlantian  (water dweller)\n\r"
" [4] Troll      (dumb and strong)\n\r"
" [5] Elf        (small but quick)\n\r"
" [6] Faerie     (small but smart)\n\r"
"-========================================-\n\r"
" Select a race -> ";