// ----------------------------------------------------------------------------
// DS Frotz
// 	
// description	:	DS version of GBA Frotz 
//					made with PAlib - www.palib.com -
//
// ----------------------------------------------------------------------------
// (c) 2006 papafuji - using PAlib
// ----------------------------------------------------------------------------

// ----------------------------------------------------------------------------
// PAlib includes
// ----------------------------------------------------------------------------

#include <PA9.h>
#include <stdio.h> 
#include <ctype.h> 

// ----------------------------------------------------------------------------
// project includes
// ----------------------------------------------------------------------------

#include "frotz.h"

#include "main.h"
#include "draw.h"
#include "sound.h"

#include "gfx/all_gfx.h"

// ----------------------------------------------------------------------------
// 
// ----------------------------------------------------------------------------

#define 		PICK_NOTHING					0
#define 		PICK_LETTER						255
#define 		PICK_SPRITE						254
#define 		PICK_BUTTON						253
#define 		PICK_TIMEOUT					252

#define 		BUTTON_A						1
#define 		BUTTON_B						2
#define 		BUTTON_X						3
#define 		BUTTON_Y						4
#define 		BUTTON_L						5
#define 		BUTTON_R						6
#define 		BUTTON_LEFT						7
#define 		BUTTON_RIGHT					8
#define 		BUTTON_UP						9
#define 		BUTTON_DOWN						10
#define 		BUTTON_START					11
#define 		BUTTON_SELECT					12

// ----------------------------------------------------------------------------
// 
// ----------------------------------------------------------------------------

extern void 	SetTextPosition( int _pos );
extern int 	GetTextPosition( void );
extern void 	ForceRedraw( void );

// ----------------------------------------------------------------------------
// 
// ----------------------------------------------------------------------------

int 		gInputMode			= 	INPUT_MODE_GRAFITI;

char		inputText[80]		=	"";
char		returnedChar		= '\0';

char		keyboardChars[]		= 	{ 	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
											'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
											'U', 'V', 'W', 'X', 'Y', 'Z', ' ', ' ', PA_ENTER, PA_BACKSPACE
									};

char		numericChars[]	= 	{ 	'1', '2', '3',  0 ,  0 , '-',  0 , '.',  0 ,  0 ,
										'4', '5', '6',  0 ,  0 , '+',  0 , ':',  0 ,  0 ,
										'7', '8', '9', '0',  0 , '*',  0 , ',',  0 , PA_BACKSPACE
									};

// ----------------------------------------------------------------------------
// 
// ----------------------------------------------------------------------------

void ChangeInputMode( void )
{
	switch( gInputMode )
	{
	case INPUT_MODE_GRAFITI :
		gInputMode 		= INPUT_MODE_KEYBOARD;
		FILL_SCREEN		( BOTTOM_SCREEN, 12 );
		PA_LoadTiledBg	( BOTTOM_SCREEN, TILED_BG_INDEX, keybd );
		SetOrder		( inputText, true );
		break;
	case INPUT_MODE_KEYBOARD :
		gInputMode 		= INPUT_MODE_NUMPAD;
		FILL_SCREEN		( BOTTOM_SCREEN, 12 );
		PA_LoadTiledBg	( BOTTOM_SCREEN, TILED_BG_INDEX, numpad );
		SetOrder		( inputText, true );
		break;
	case INPUT_MODE_NUMPAD :
		gInputMode 		= INPUT_MODE_GRAFITI;
		FILL_SCREEN		( BOTTOM_SCREEN, 12 );
		PA_LoadTiledBg	( BOTTOM_SCREEN, TILED_BG_INDEX, bottom );
		SetOrder		( inputText, true );
		break;
	}
}

// ----------------------------------------------------------------------------
// 
// ----------------------------------------------------------------------------

int Pause( void )
{
	int		returnValue = 0;
	
	HideSprites		();
	PA_DeleteBg		( BOTTOM_SCREEN, TILED_BG_INDEX );
	FILL_SCREEN		( BOTTOM_SCREEN, 17 );
	PRINT_CSTRING	( BOTTOM_SCREEN, "- pause -", 		64, 31, 7, 240 );
	PRINT_CSTRING	( BOTTOM_SCREEN, "- continue -", 	96, 31, 7, 240 );
	PRINT_CSTRING	( BOTTOM_SCREEN, "- exit game -", 	128, 31, 7, 240 );

	while( true )
	{
		if ( Stylus.Newpress )
		{
			if ( ( Stylus.Y >= 96 && Stylus.Y <= 104 ) || ( Stylus.Y >= 128 && Stylus.Y <= 160 ) )
			{
				while( Stylus.Held ) PA_WaitForVBL();
				if ( Stylus.Y >= 96 && Stylus.Y <= 104 )
				{
					//PA_WaitForVBL();
					returnValue = 0;
					break;
				}
				if ( Stylus.Y >= 128 && Stylus.Y <= 136 )
				{
					//PA_WaitForVBL();
					returnValue = -1;
					break;
				}
			}
		}
		PA_WaitForVBL();
	}

	switch ( gInputMode )
	{
	case INPUT_MODE_GRAFITI 	: PA_LoadTiledBg	( BOTTOM_SCREEN, TILED_BG_INDEX, bottom );  break;
	case INPUT_MODE_KEYBOARD	: PA_LoadTiledBg	( BOTTOM_SCREEN, TILED_BG_INDEX, keybd ); break;
	case INPUT_MODE_NUMPAD		: PA_LoadTiledBg	( BOTTOM_SCREEN, TILED_BG_INDEX, numpad ); break;
	}
	
	PA_WaitForVBL();
	
	ShowSprites		();
	RefreshScreens	( 3 );

	return returnValue ;
}

// ----------------------------------------------------------------------------
// 
// ----------------------------------------------------------------------------

void Wait( void )
{
	while( true )
	{
		PA_WaitForVBL();
		if ( 	Stylus.Newpress 	|| 
				Pad.Newpress.A 		|| Pad.Newpress.B 		|| Pad.Newpress.X 	|| Pad.Newpress.Y 		||
				Pad.Newpress.Left 	|| Pad.Newpress.Right 	|| Pad.Newpress.Up 	|| Pad.Newpress.Down	||
				Pad.Newpress.L 		|| Pad.Newpress.R 
			)
		{
			break;
		}
	}
	
	SoundPlay( SOUND_CLICK );
	PA_WaitForVBL();
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// CHAR INPUT
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

#define RETURN_VALUE( _type_, _value_ )		\
	{										\
		PA_WaitForVBL();					\
		*_data = _value_;					\
		return _type_;						\
	}
				
// ----------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------

char ProcessInput(	int* 	_timeout, 		// en 1/60 de secondes
					int*	_data
				 )
{
	bool		checkletter = false;
	char		letter		= 0;
	int			pickedSprite;

	if ( *_timeout <= 1 )
	{
		*_timeout = -1;
	}		
		
	while( true )
	{
		bool skipVBL = false;
		
		if ( *_timeout == 0 )
			return PICK_TIMEOUT;
		
		if ( checkletter )
		{
			PA_8bitDraw( BOTTOM_SCREEN, 8 );

			letter = PA_CheckLetter();
			
			if 	( 	( letter == ' ' ) ||
					( letter == PA_ENTER ) ||
					( letter == PA_BACKSPACE ) )
			{
				RETURN_VALUE( PICK_LETTER, letter );
			}
			else if ( isalpha( letter ) ) 			// there is a new letter
			{ 
				RETURN_VALUE( PICK_LETTER, toupper( letter ) );
			}

			//checkletter = false;
		}
		else if ( Stylus.Newpress )
		{
			if ( fatalMessage[0] ) return -1;
			SetMessage( "" );
			RefreshScreens( 0 );
			checkletter = false;
			if ( (gInputMode == INPUT_MODE_KEYBOARD) || (gInputMode == INPUT_MODE_NUMPAD) )
			{
				if ( Stylus.X >=40 && Stylus.X < 217  && Stylus.Y >=102 && Stylus.Y < 160 )
				{
					int 	keyIndex	= ((Stylus.X-40) / 18) + 10 * ((Stylus.Y-102) / 18);
					if ( keyIndex >= 0 && keyIndex < 30 )
					{
						char	c 			= (gInputMode == INPUT_MODE_NUMPAD)	? numericChars[keyIndex]
																				: keyboardChars[keyIndex];
						if ( c != 0 )
						{
							RETURN_VALUE( PICK_LETTER, c );
						}
					}
				}
			}
			if ( (pickedSprite = PickSprite( Stylus.X, Stylus.Y )) > -1 )
			{
				RETURN_VALUE( PICK_SPRITE, pickedSprite );
			}
			else
			{
				checkletter = true;
				skipVBL 	= true;
			}
		}
		else if ( Pad.Newpress.Up )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_UP );
		}
		else if ( Pad.Newpress.Down )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_DOWN );
		}
		else if ( Pad.Newpress.Left )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_LEFT );
		}
		else if ( Pad.Newpress.Right )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_RIGHT );
		}
		else if ( Pad.Newpress.L )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_L );
		}
		else if ( Pad.Newpress.R )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_R );
		}
		else if ( Pad.Newpress.A )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_A );
		}
		else if ( Pad.Newpress.B )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_B );
		}
		else if ( Pad.Newpress.Y )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_Y );
		}
		else if ( Pad.Newpress.X )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_X );
		}
		else if ( Pad.Newpress.Start )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_START );
		}
		else if ( Pad.Newpress.Select )
		{
			RETURN_VALUE( PICK_BUTTON, BUTTON_SELECT );
		}
		if ( !skipVBL )
		{
			PA_WaitForVBL();
			if ( _timeout > 0 ) 
			{
				*_timeout = *_timeout - 1; 
			}				
		}
	}

	RETURN_VALUE( 0, 0 );
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// CHAR INPUT
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

char ProcessInputChar( int _timeout )		// timeout en 1/10s de seonde
{
	int 		timeout 		= _timeout * 60 / 10;
	int			data			= 0;
	bool		continueInput	= true;
	
	SetOrder( "", true );
	
	while( continueInput )
	{
		switch( ProcessInput( &timeout, &data ) )
		{
		case PICK_NOTHING 	: 
			break;
		case PICK_TIMEOUT 	: 
			returnedChar	= ZC_TIME_OUT;
			continueInput	= false;
			break;
		case PICK_LETTER 	: 
			returnedChar	= (char)data;
			continueInput	= false;
			break;
		case PICK_SPRITE 	:
			returnedChar	= ZC_RETURN;
			continueInput	= false;
			break;
		case PICK_BUTTON :
			switch( data )
			{
			case BUTTON_A :
				returnedChar 	= ( gGameID == GAME_ID_FREEFALL ) ? 's' : ZC_RETURN;
				continueInput	= false;
				break;
			case BUTTON_B :
				returnedChar 	= ZC_ESCAPE;
				continueInput	= false;
				break;
			case BUTTON_UP :
				returnedChar 	= ( gGameID == GAME_ID_FREEFALL ) ? ' ' : ZC_ARROW_UP;
				continueInput	= false;
				break;
			case BUTTON_DOWN :
				returnedChar 	= ( gGameID == GAME_ID_FREEFALL ) ? 'z' : ZC_ARROW_DOWN;
				continueInput	= false;
				break;
			case BUTTON_LEFT :
				returnedChar 	= ( gGameID == GAME_ID_FREEFALL ) ? 'a' : ZC_ARROW_LEFT;
				continueInput	= false;
				break;
			case BUTTON_RIGHT :
				returnedChar 	= ( gGameID == GAME_ID_FREEFALL ) ? 'd' : ZC_ARROW_RIGHT;
				continueInput	= false;
				break;
			case BUTTON_Y :			// Y = yes
				returnedChar 	= 'Y';
				continueInput	= false;
				break;
			case BUTTON_X :			// X = change input mode
				ChangeInputMode();
				break;
			}
			break;
		}
		PA_WaitForVBL();
	}

	
	return returnedChar;
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// TEXT INPUT
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

int ProcessInputString( char* _text, int _timeout )
{
	int 	data			= 0;
	int		nletter 		= 0;
//	int		pickedSprite	= -1;
	bool	continueInput	= true;
	int 	timeout 		= _timeout * 60 / 10;
	char*	txt				= NULL;
	
	*inputText = '\0';
	SetOrder( "", true );
	TextCompletionInit();
	
	while( continueInput )
	{
		switch( ProcessInput( &timeout, &data ) )
		{
		case PICK_TIMEOUT 	: 
			return ZC_TIME_OUT;

		case PICK_NOTHING :
			break;

		case PICK_LETTER 	: 
			if ( data == PA_ENTER )						// ENTER = text competion 
			{
				if ( nletter > 0 )
				{
					nletter = TextCompletion( inputText, gMainChars );
				}
				SetOrder( inputText, true );
			}
			else if ( data == PA_BACKSPACE ) 			// BACKSPACE = erase the last character
			{ 
				if ( nletter )
				{
					nletter--;
					inputText[nletter] = '\0';
				}
				TextCompletionInit();
				SetOrder( inputText, true );
			}
			else if ( data )			 				// OTHER CASE = a new letter is added
			{ 
				if ( islower( data ) )  data = toupper( data );
				if ( (data == ' ' ) && ((nletter==0) || inputText[nletter-1] == ' ' ) )
				{
					// ignore starting or redonding spaces
				}
				else
				{
					inputText[nletter] = data;
					nletter++;
					inputText[nletter] = '\0';
				}
				TextCompletionInit();
				SetOrder( inputText, true );
			}
			break;

		case PICK_SPRITE 	:
			txt = GetSpriteText( data );
			if ( !strcmp( txt, "OK" ) ) 
			{
				continueInput	= false;
				break;
			}
			strcpy( inputText, txt ); 
			nletter = strlen( inputText );
			SetOrder( inputText, true );
			break;
				
		case PICK_BUTTON :
			if ( data == BUTTON_L )
			{
			} 
			else if ( data == BUTTON_R )
			{
			} 
			else if ( data == BUTTON_LEFT )
			{
			} 
			else if ( data == BUTTON_RIGHT )
			{
			} 
			else if ( data == BUTTON_UP )
			{
			} 
			else if ( data == BUTTON_DOWN )
			{
			} 
			else if ( data == BUTTON_A )
			{
				continueInput	= false;
				break;
			} 
			else if ( data == BUTTON_B )
			{
				strcpy( inputText, "" );
				nletter = strlen( inputText );
				SetOrder( inputText, true );
			} 
			else if ( data == BUTTON_X )
			{
				ChangeInputMode();
			} 
			else if ( data == BUTTON_Y )
			{
				/*strcpy( inputText[0] = '\0';
				nletter = strlen( inputText );
				SetOrder( inputText, true );
				*/
			} 
			else if ( ( data == BUTTON_START ) || ( data == BUTTON_SELECT ) )
			{ 
				if ( fatalMessage[0] ) return -1;
				if ( Pause() < 0 )
				{
					PA_WaitForVBL();
					return -1;
				}
			}
			break;
		}

		PA_WaitForVBL();
	}

	// special DS version shortcuts

	if 		( !strcmp( inputText, "I" ) 	|| !strcmp( inputText, "IN" ) || !strcmp( inputText, "INV" ) )
		strcpy( _text, "INVENTORY" );
	else if ( !strcmp( inputText, "H" ) 	|| !strcmp( inputText, "HLP" ) )
		strcpy( _text, "HELP" );
	else if ( !strcmp( inputText, "SC" ) 	|| !strcmp( inputText, "SCO" ) )
		strcpy( _text, "SCORE" );
	else if ( !strcmp( inputText, "SV" ) 	|| !strcmp( inputText, "SAV" ) )
		strcpy( _text, "SAVE" );
	else if ( !strcmp( inputText, "R" )		|| !strcmp( inputText, "RST" ) || !strcmp( inputText, "RESTO" ) )
		strcpy( _text, "RESTORE" );
	else if ( !strcmp( inputText, "DBG" ) )
	{
		gDSdebugMode = 1;
		strcpy( _text, "" );
	}
	else if ( !strcmp( inputText, "NODBG" ) )
	{
		gDSdebugMode = 0;
		strcpy( _text, "" );
	}
	else
	{
		strcpy( _text, inputText );
	}

	PA_WaitForVBL();
	TextCompletionInit();
	
	return 1;
}

// ----------------------------------------------------------------------------
// (c) papafuji - 2006 - using PAlib
// ----------------------------------------------------------------------------

