/* Copyright (C) 1995-2002  FSGames. Ported by Sean Ford and Yan Shosh
 *
 * 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
 */
//
// input.cpp
//
// input code
//

#include "input.h"
#include <stdio.h>
#include <time.h>
#include <string.h> //buffers: for strlen
#include <string>

extern int want_keystroke ;
extern int doinggame ;
extern int *normalkeys[] ;

long quit(long arg1);

int raw_key;
short key_press_event = 0;    // used to signed key-press
bool *key_list;

long mouse_state[MSTATE];
long mouse_buttons;

int mult = 500;

// Zardus: add: arrays to keep track of joystick data
int *joy_numaxes;
int *joy_startval;
int *joy_numbuttons;

SDL_Joystick *joysticks[4];

#define KEY_UP                  0
#define KEY_UP_RIGHT            1
#define KEY_RIGHT               2
#define KEY_DOWN_RIGHT          3
#define KEY_DOWN                4
#define KEY_DOWN_LEFT           5
#define KEY_LEFT                6
#define KEY_UP_LEFT             7
#define KEY_FIRE                8
#define KEY_SPECIAL             9
#define KEY_SWITCH              10
#define KEY_SPECIAL_SWITCH      11
#define KEY_YELL                12
#define KEY_SHIFTER             13
#define KEY_PREFS               14
#define KEY_CHEAT               15
//
// Input routines (for handling all events and then setting the appropriate vars)
//

int myFilter( const SDL_Event *event )
{
	if ( event->type == SDL_JOYHATMOTION )
		return 0 ;

	return 1 ;
}

static const char *arrow[] = {
  /* width height num_colors chars_per_pixel */
  "    32    32        3            1",
  /* colors */
  "X c #000000",
  ". c #ffffff",
  "  c None",
  /* pixels */
  "X                               ",
  "XX                              ",
  "X.X                             ",
  "X..X                            ",
  "X...X                           ",
  "X....X                          ",
  "X.....X                         ",
  "X......X                        ",
  "X.......X                       ",
  "X........X                      ",
  "X.....XXXXX                     ",
  "X..X..X                         ",
  "X.X X..X                        ",
  "XX  X..X                        ",
  "X    X..X                       ",
  "     X..X                       ",
  "      X..X                      ",
  "      X..X                      ",
  "       XX                       ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "0,0"
};

static SDL_Cursor *init_system_cursor(const char *image[])
{
  int i, row, col;
  Uint8 data[4*32];
  Uint8 mask[4*32];
  int hot_x, hot_y;

  i = -1;
  for ( row=0; row<32; ++row ) {
    for ( col=0; col<32; ++col ) {
      if ( col % 8 ) {
        data[i] <<= 1;
        mask[i] <<= 1;
      } else {
        ++i;
        data[i] = mask[i] = 0;
      }
      switch (image[4+row][col]) {
        case 'X':
          data[i] |= 0x01;
          mask[i] |= 0x01;
          break;
        case '.':
          mask[i] |= 0x01;
          break;
        case ' ':
          break;
      }
    }
  }
  sscanf(image[4+row], "%d,%d", &hot_x, &hot_y);
  return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
}

void init_input()
{
	int numjoy, i;
	int listlength = MAXKEYS;
	SDL_Joystick *js;
	SDL_Cursor *newcursor ;

	numjoy = SDL_NumJoysticks();
	joy_numaxes = new int[numjoy];
	joy_startval = new int[numjoy];
	joy_numbuttons = new int[numjoy];

	for (i = 0; i < numjoy; i++)
	{
		joysticks[i] = js = SDL_JoystickOpen(i);
		joy_numaxes[i] = SDL_JoystickNumAxes(js);
		joy_numbuttons[i] = SDL_JoystickNumButtons(js);
		joy_startval[i] = listlength;
		listlength += SDL_JoystickNumAxes(js) * 2 + SDL_JoystickNumButtons(js);
	}

	key_list = new bool[listlength];

	SDL_JoystickEventState(SDL_ENABLE);

	memset( mouse_state, 0, sizeof(long)*MSTATE ) ;

	SDL_SetEventFilter( myFilter ) ;
	//newcursor = init_system_cursor(arrow) ;

	//if ( newcursor )
		//SDL_SetCursor( newcursor ) ;

}



void stop_input()
{
	delete key_list;
	delete joy_numaxes;
	delete joy_startval;
	delete joy_numbuttons;

	key_list = NULL;
	joy_numaxes = NULL;
	joy_startval = NULL;
	joy_numbuttons = NULL;
}

void get_input_events(bool type)
{


	SDL_Event event;

	if (type == POLL)
		while (SDL_PollEvent(&event))
			handle_events(&event);
	if (type == WAIT)
	{
		SDL_WaitEvent(&event);
		handle_events(&event);
	}
}

void update_mouse_pos()
{
	SDL_Joystick *js;
	int x, y, i ;
	int numjoy ;

	numjoy = SDL_NumJoysticks();

	for (i = 0; i < numjoy; i++)
	{
		js = SDL_JoystickOpen(i);

		if ( js ) 
		{
			x = SDL_JoystickGetAxis( js, 0 ) ;
			y = SDL_JoystickGetAxis( js, 1 ) ;

			if ( ( abs(x) > 9000 ) || ( abs(y) > 9000 ) )
			{
				if ( abs(x) > 9000 )
				{
					if ( x > 0 )
						x -= 9000 ;
					else
						x += 9000 ;

					mouse_state[MOUSE_X] += x/2000 ; 
				}

				if ( abs(y) > 9000 )
				{
					if ( y > 0 )
						y -= 9000 ;
					else
						y += 9000 ;

					mouse_state[MOUSE_Y] += y/2000  ;
				}

				if ( mouse_state[MOUSE_X] < 0 )
					mouse_state[MOUSE_X] = 0 ;

				if ( mouse_state[MOUSE_X] > 319 )
					mouse_state[MOUSE_X] = 319 ;

				if ( mouse_state[MOUSE_Y] < 0 )
					mouse_state[MOUSE_Y] = 0 ;

				if ( mouse_state[MOUSE_Y] > 239 )
					mouse_state[MOUSE_Y] = 239 ;

				//SDL_ShowCursor( SDL_ENABLE ) ;
				//SDL_WarpMouse( mouse_state[MOUSE_X],mouse_state[MOUSE_Y] ) ;
				break ;
			}
		}
	}
}

void handle_events(SDL_Event *event)
{
	int key ;

	switch (event->type)
	{
			// Key pressed or released:
		case SDL_KEYDOWN:
			key_list[event->key.keysym.sym] = 1;
			raw_key = event->key.keysym.sym;
			key_press_event = 1;
			break;
		case SDL_KEYUP:
			key_list[event->key.keysym.sym] = 0;
			break;

			// Mouse event
		case SDL_MOUSEMOTION:
			//mouse_state[MOUSE_X] = event->motion.x / mult;
			//mouse_state[MOUSE_Y] = event->motion.y / mult;
			break;
		case SDL_MOUSEBUTTONUP:
			if (event->button.button == SDL_BUTTON_LEFT)
				mouse_state[MOUSE_LEFT] = 0;
			if (event->button.button == SDL_BUTTON_RIGHT)
				mouse_state[MOUSE_RIGHT] = 0;
			//mouse_state[MOUSE_LEFT] = SDL_BUTTON(SDL_BUTTON_LEFT);
			//printf ("LMB: %d",  SDL_BUTTON(SDL_BUTTON_LEFT));
			//mouse_state[MOUSE_RIGHT] = SDL_BUTTON(SDL_BUTTON_RIGHT);
			//printf ("RMB: %d",  SDL_BUTTON(SDL_BUTTON_RIGHT));
			break;
		case SDL_MOUSEBUTTONDOWN:
			if (event->button.button == SDL_BUTTON_LEFT)
				mouse_state[MOUSE_LEFT] = 1;
			if (event->button.button == SDL_BUTTON_RIGHT)
				mouse_state[MOUSE_RIGHT] = 1;
			break;
		case SDL_JOYAXISMOTION:
			//which = joypad, value = value, axis0 = x, axis1 = y, neg y = up, pos x = right
			if (event->jaxis.value > 1)
			{
				key_list[joy_startval[event->jaxis.which] + event->jaxis.axis * 2] = 1;
				key_list[joy_startval[event->jaxis.which] + event->jaxis.axis * 2 + 1] = 0;
				key_press_event = 1;
				raw_key = joy_startval[event->jaxis.which] + event->jaxis.axis * 2;
			}
			else if (event->jaxis.value < -1)
			{
				key_list[joy_startval[event->jaxis.which] + event->jaxis.axis * 2] = 0;
				key_list[joy_startval[event->jaxis.which] + event->jaxis.axis * 2 + 1] = 1;
				key_press_event = 1;
				raw_key = joy_startval[event->jaxis.which] + event->jaxis.axis * 2 + 1;
			}
			else
			{
				key_list[joy_startval[event->jaxis.which] + event->jaxis.axis * 2] = 0;
				key_list[joy_startval[event->jaxis.which] + event->jaxis.axis * 2 + 1] = 0;
			}
			break;
		case SDL_JOYBUTTONDOWN:
			key_list[joy_startval[event->jbutton.which] + joy_numaxes[event->jbutton.which] * 2 + event->jbutton.button] = 1;
			raw_key = joy_startval[event->jbutton.which] + joy_numaxes[event->jbutton.which] * 2 + event->jbutton.button;
			key_press_event = 1;
//#define XINPUT_GAMEPAD_A			0  fire
//#define XINPUT_GAMEPAD_B			1 yell
//#define XINPUT_GAMEPAD_X			2  special
//#define XINPUT_GAMEPAD_Y			3  shifter
//#define XINPUT_GAMEPAD_BLACK		4
//#define XINPUT_GAMEPAD_WHITE		5
//#define XINPUT_GAMEPAD_LEFT_TRIGGER		6 switch guys
//#define XINPUT_GAMEPAD_RIGHT_TRIGGER		7 change special
//start  8  options
//back  9  escape
//left thumb  10  cheat
//right thumb  11
//dpad up  12
//down 13
//left   14
//right  15

//     F: gain flight  B
     //H: gain hitpoints  A
     //M: gain magicpoints  X
     //S: gain temporary movement speed increase  Y
     //T: tranform to another character type BLACK
     //V: gain invisibility  WHITE
   //[,]: (left & right brackets) temporarily  LEFT/RIGHT Trigger
        //lower or raise your level
   //F12: kill all LIVING enemies on the  START
        //level

			if ( doinggame )
			{
				if ( ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 10 ) ) )// cheat button pressed
				{
					switch( event->jbutton.button )
					{
						case 0  : raw_key = SDLK_f ; break ; 
						case 1  : raw_key = SDLK_h ; break ; 
						case 2  : raw_key = SDLK_m ; break ; 
						case 3  : raw_key = SDLK_s ; break ; 
						case 4  : raw_key = SDLK_t ; break ; 
						case 5  : raw_key = SDLK_v ; break ; 
						case 6  : raw_key = SDLK_LEFTBRACKET ; break ; 
						case 7  : raw_key = SDLK_RIGHTBRACKET ; break ; 
						case 8  : raw_key = SDLK_F12 ; break ; 
						case 10 : raw_key = normalkeys[event->jbutton.which][KEY_CHEAT] ; break ;
						default : raw_key = SDLK_9 ; break ; 
					}
				}
				else
				{
					switch( event->jbutton.button )
					{
						case 0  : raw_key = normalkeys[event->jbutton.which][KEY_FIRE] ; break ;
						case 1  : raw_key = normalkeys[event->jbutton.which][KEY_YELL] ; break ;
						case 2  : raw_key = normalkeys[event->jbutton.which][KEY_SPECIAL] ; break ;
						case 3  : raw_key = normalkeys[event->jbutton.which][KEY_SHIFTER] ; break ;
						case 6  : raw_key = normalkeys[event->jbutton.which][KEY_SWITCH] ; break ;
						case 7  : raw_key = normalkeys[event->jbutton.which][KEY_SPECIAL_SWITCH] ; break ;
						case 8  : raw_key = normalkeys[event->jbutton.which][KEY_PREFS] ; break ;
						case 9  : raw_key = SDLK_ESCAPE ; break ;
						case 10 : raw_key = normalkeys[event->jbutton.which][KEY_CHEAT] ; break ;
						case 12 :
						{
							for ( key = 0 ; key < 8 ; key++ ) key_list[normalkeys[event->jbutton.which][key]] = 0 ;
							if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 14 ) )
								raw_key = normalkeys[event->jbutton.which][KEY_UP_LEFT] ;
							else if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 15 ) )
								raw_key = normalkeys[event->jbutton.which][KEY_UP_RIGHT] ;
							else
								raw_key = normalkeys[event->jbutton.which][KEY_UP] ;
							break ;
						}
						case 13 :
						{
							for ( key = 0 ; key < 8 ; key++ ) key_list[normalkeys[event->jbutton.which][key]] = 0 ;
							if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 14 ) )
								raw_key = normalkeys[event->jbutton.which][KEY_DOWN_LEFT] ;
							else if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 15 ) )
								raw_key = normalkeys[event->jbutton.which][KEY_DOWN_RIGHT] ;
							else
								raw_key = normalkeys[event->jbutton.which][KEY_DOWN] ;
							break ;
						}
						case 14 :
						{
							for ( key = 0 ; key < 8 ; key++ ) key_list[normalkeys[event->jbutton.which][key]] = 0 ;
							if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 12 ) )
								raw_key = normalkeys[event->jbutton.which][KEY_UP_LEFT] ;
							else if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 13 ) )
								raw_key = normalkeys[event->jbutton.which][KEY_DOWN_LEFT] ;
							else
								raw_key = normalkeys[event->jbutton.which][KEY_LEFT] ;
							break ;
						}
						case 15 :
						{
							for ( key = 0 ; key < 8 ; key++ ) key_list[normalkeys[event->jbutton.which][key]] = 0 ;
							if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 12 ) )
								raw_key = normalkeys[event->jbutton.which][KEY_UP_RIGHT] ;
							else if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 13 ) )
								raw_key = normalkeys[event->jbutton.which][KEY_DOWN_RIGHT] ;
							else
								raw_key = normalkeys[event->jbutton.which][KEY_RIGHT] ;
							break ;
						}
						default : raw_key = SDLK_9 ; break ; 
					}
				}
				key_list[raw_key] = 1;
				key_press_event = 1;

			}
			else
			{
				switch( event->jbutton.button )
				{
					case 0 : 
					{
						mouse_state[MOUSE_LEFT] = 1;

						if ( want_keystroke )
						{
							key_list[SDLK_RETURN] = 1;
							raw_key = SDLK_RETURN;
							key_press_event = 1;
						}

						break ;
					}
					case 1 : 
					{
						key_list[SDLK_ESCAPE] = 1;
						raw_key = SDLK_ESCAPE;
						key_press_event = 1;
						break ;
					}
					default : break ;
				}
			}

			break;
		case SDL_JOYBUTTONUP:
			key_list[joy_startval[event->jbutton.which] + joy_numaxes[event->jbutton.which] * 2 + event->jbutton.button] = 0;
			if( doinggame ) 
			{
				if ( ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 10 ) ) ) // cheat button pressed
				{
					switch( event->jbutton.button )
					{
						case 0  : raw_key = SDLK_f ; break ; 
						case 1  : raw_key = SDLK_h ; break ; 
						case 2  : raw_key = SDLK_m ; break ; 
						case 3  : raw_key = SDLK_s ; break ; 
						case 4  : raw_key = SDLK_t ; break ; 
						case 5  : raw_key = SDLK_v ; break ; 
						case 6  : raw_key = SDLK_LEFTBRACKET ; break ; 
						case 7  : raw_key = SDLK_RIGHTBRACKET ; break ; 
						case 8  : raw_key = SDLK_F12 ; break ; 
						case 10 : raw_key = normalkeys[event->jbutton.which][KEY_CHEAT] ; break ;
						default : raw_key = SDLK_9 ; break ; 
					}
				}
				else
				{
					switch( event->jbutton.button )
					{
						case 0  : raw_key = normalkeys[event->jbutton.which][KEY_FIRE] ; break ;
						case 1  : raw_key = normalkeys[event->jbutton.which][KEY_YELL] ; break ;
						case 2  : raw_key = normalkeys[event->jbutton.which][KEY_SPECIAL] ; break ;
						case 3  : raw_key = normalkeys[event->jbutton.which][KEY_SHIFTER] ; break ;
						case 6  : raw_key = normalkeys[event->jbutton.which][KEY_SWITCH] ; break ;
						case 7  : raw_key = normalkeys[event->jbutton.which][KEY_SPECIAL_SWITCH] ; break ;
						case 8  : raw_key = normalkeys[event->jbutton.which][KEY_PREFS] ; break ;
						case 9  : raw_key = SDLK_ESCAPE ; break ;
						case 10 : clear_keyboard() ; break ; //release cheat key - set all to 0 just to be sure
						case 12 :
						{
							for ( key = 0 ; key < 8 ; key++ ) key_list[normalkeys[event->jbutton.which][key]] = 0 ;
							if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 14 ) )
								key_list[normalkeys[event->jbutton.which][KEY_LEFT]] = 1 ;
							else if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 15 ) )
								key_list[normalkeys[event->jbutton.which][KEY_RIGHT]] = 1 ;
							raw_key = SDLK_9 ; 
							break ;
						}
						case 13 :
						{
							for ( key = 0 ; key < 8 ; key++ ) key_list[normalkeys[event->jbutton.which][key]] = 0 ;
							if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 14 ) )
								key_list[normalkeys[event->jbutton.which][KEY_LEFT]] = 1 ;
							else if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 15 ) )
								key_list[normalkeys[event->jbutton.which][KEY_RIGHT]] = 1 ;
							raw_key = SDLK_9 ; 
							break ;
						}
						case 14 :
						{
							for ( key = 0 ; key < 8 ; key++ ) key_list[normalkeys[event->jbutton.which][key]] = 0 ;
							if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 12 ) )
								key_list[normalkeys[event->jbutton.which][KEY_UP]] = 1 ;
							else if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 13 ) )
								key_list[normalkeys[event->jbutton.which][KEY_DOWN]] = 1 ;
							raw_key = SDLK_9 ; 
							break ;
						}
						case 15 :
						{
							for ( key = 0 ; key < 8 ; key++ ) key_list[normalkeys[event->jbutton.which][key]] = 0 ;
							if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 12 ) )
								key_list[normalkeys[event->jbutton.which][KEY_UP]] = 1 ;
							else if ( SDL_JoystickGetButton( joysticks[event->jbutton.which], 13 ) )
								key_list[normalkeys[event->jbutton.which][KEY_DOWN]] = 1 ;
							raw_key = SDLK_9 ; 
							break ;
						}
						default : raw_key = SDLK_9 ; break ; 
					}
				}
				key_list[raw_key] = 0;
			}
			else
			{
				switch( event->jbutton.button )
				{
					case 0 : 
					{
						mouse_state[MOUSE_LEFT] = 0;
						break ;
					}
					case 1 : 
					{
						key_list[SDLK_ESCAPE] = 0;
						break ;
					}
					default : break ;
				}
			}
			break;
		case SDL_QUIT:
			quit(1);
			break;
		default:
			break;
	}
}


//
//Keyboard routines
//

void grab_keyboard()
{}

void release_keyboard()
{}

int query_key()
{
	return raw_key;
}

//
// Set the keyboard array to all zeros, the
// virgin state, nothing depressed
//
void clear_keyboard()
{
	int i = 0;
	for (i = 0; i < MAXKEYS; i++)
		key_list[i] = 0;
	key_press_event = 0;
	raw_key = 0;
}

char * query_keyboard()
{
	return (char *) key_list;
}

void wait_for_key(int somekey)
{
	// First wait for key press ..
	while (!key_list[somekey])
		get_input_events(WAIT);

	// And now for the key to be released ..
	while (key_list[somekey])
		get_input_events(WAIT);
}

short query_key_press_event()
{

	return key_press_event;
}

void clear_key_press_event()
{
	key_press_event = 0;
}

short query_key_code(int code)
{
	return key_list[code];
}

void clear_key_code(int code)
{
	key_list[code] = 0;
}

void enable_keyrepeat()
{
	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL);
}

void disable_keyrepeat()
{
	SDL_EnableKeyRepeat(0,0);
}



//
// Mouse routines
//

void grab_mouse()
{
	//SDL_ShowCursor(SDL_ENABLE);
}

void release_mouse()
{
	//SDL_ShowCursor(SDL_DISABLE);
}

long * query_mouse()
{
	// The mouse_state thing is set using get_input_events, though
	// it should probably get its own function
	get_input_events(POLL);
	return mouse_state;
}

// Zardus: add: this sets the multiplier mult
void set_mult(int m)
{
	mult = m;
}
