/* MoleInvasion - Copyright (C) - Guillaume Chambraud (linuxprocess@free.fr)

  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. */

#include <assert.h>
#include "events.h"
#include "tool.h"

/* configurable keys */
# define MIK_LEFT	0
# define MIK_RIGHT	1
# define MIK_DOWN	2
# define MIK_UP		3
# define MIK_ACCEL	4
# define MIK_SPECIAL	5
# define MIK_JUMP	6

/* config par défaut */
static key_config_desc key_config[] = 
{{SDLK_LEFT	,NULL,	-1	,"[LEFT_KEY]"		},
 {SDLK_RIGHT	,NULL,	-1	,"[RIGHT_KEY]"		},
 {SDLK_DOWN	,NULL,	-1	,"[DOWN_KEY]"		},
 {SDLK_UP	,NULL,	-1	,"[UP_KEY]"		},
 {SDLK_a	,NULL,	 0	,"[ACCEL_KEY]"		},
 {SDLK_q	,NULL,	 1	,"[SPECIAL_KEY]"	},
 {SDLK_UP	,NULL,	 2	,"[JUMP_KEY]"		}};

static all_events_status all_current_events;
static char any_key_pressed;

/* réinitialise seuls les évènements "key-pressed" */
void events_kp_init()
{	all_current_events.F1_kp	= all_current_events.F2_kp      = 
	all_current_events.F3_kp	= all_current_events.F4_kp      = 
	all_current_events.F5_kp	= all_current_events.F6_kp      = 
	all_current_events.F7_kp	= all_current_events.F8_kp      = 

	all_current_events.n0_kp        = all_current_events.n1_kp      = 
	all_current_events.n2_kp        = all_current_events.n3_kp      = 
	all_current_events.n4_kp        = all_current_events.n5_kp      = 
	all_current_events.n6_kp        = all_current_events.n7_kp      = 
	all_current_events.n8_kp        = all_current_events.n9_kp      = 

	all_current_events.d_kp = all_current_events.j_kp =
	all_current_events.y_kp = all_current_events.o_kp =
	all_current_events.s_kp = all_current_events.n_kp =
	all_current_events.f_kp = all_current_events.p_kp =
	
	all_current_events.special_kp = all_current_events.jump_kp =
	
	all_current_events.arrow_up_kp   = all_current_events.arrow_down_kp  =
	all_current_events.arrow_left_kp = all_current_events.arrow_right_kp = 
	all_current_events.return_kp     = 0;
}

/* réinitialise tous les évènements */
void events_init()
{	all_current_events.left		= all_current_events.right	=
	all_current_events.jump		= all_current_events.down	=
	all_current_events.space	= all_current_events.quit	=
	all_current_events.esc		= all_current_events.accel	= 
	any_key_pressed	= 0;
	events_kp_init();
}

static void handle_key( SDLKey key, int pressed )
{
	/* configurable keys */
	if(key==key_config[MIK_LEFT].key)
	   all_current_events.left =pressed;
	if(key==key_config[MIK_RIGHT].key)
	   all_current_events.right=pressed;
	if(key==key_config[MIK_DOWN].key)
	   all_current_events.down =pressed;
	if(key==key_config[MIK_UP].key)
	   all_current_events.up =pressed;
	if(key==key_config[MIK_ACCEL].key)
	   all_current_events.accel=pressed;
	if(key==key_config[MIK_JUMP].key)
	   all_current_events.jump =pressed;
	/* others */
	switch( key ) {
	case SDLK_SPACE:	all_current_events.space=pressed; break;
	case SDLK_ESCAPE:	all_current_events.esc	=pressed; break;
	default:	break;
	}

	if(pressed)
	{	/* configurable keys */
		if(key==key_config[MIK_JUMP].key)
			all_current_events.jump_kp = 1;
		else if(key==key_config[MIK_SPECIAL].key)
			all_current_events.special_kp = 1;
		/* others */
		switch( key ) {
		case SDLK_F1:	all_current_events.F1_kp = 1; break;
		case SDLK_F2:	all_current_events.F2_kp = 1; break;
		case SDLK_F3:	all_current_events.F3_kp = 1; break;
		case SDLK_F4:	all_current_events.F4_kp = 1; break;
		case SDLK_F5:	all_current_events.F5_kp = 1; break;
		case SDLK_F6:	all_current_events.F6_kp = 1; break;
		case SDLK_F7:	all_current_events.F7_kp = 1; break;
		case SDLK_F8:	all_current_events.F8_kp = 1; break;

		case SDLK_0:case SDLK_KP0:case SDLK_WORLD_64:	all_current_events.n0_kp = 1; break;
		case SDLK_1:case SDLK_KP1:case SDLK_AMPERSAND:	all_current_events.n1_kp = 1; break;
		case SDLK_2:case SDLK_KP2:case SDLK_WORLD_73:	all_current_events.n2_kp = 1; break;
		case SDLK_3:case SDLK_KP3:case SDLK_QUOTEDBL:	all_current_events.n3_kp = 1; break;
		case SDLK_4:case SDLK_KP4:case SDLK_QUOTE:	all_current_events.n4_kp = 1; break;
		case SDLK_5:case SDLK_KP5:case SDLK_LEFTPAREN:	all_current_events.n5_kp = 1; break;
		case SDLK_6:case SDLK_KP6:case SDLK_MINUS:	all_current_events.n6_kp = 1; break;
		case SDLK_7:case SDLK_KP7:case SDLK_WORLD_72:	all_current_events.n7_kp = 1; break;
		case SDLK_8:case SDLK_KP8:case SDLK_UNDERSCORE:	all_current_events.n8_kp = 1; break;
		case SDLK_9:case SDLK_KP9:case SDLK_WORLD_71:	all_current_events.n9_kp = 1; break;

		case SDLK_d:	all_current_events.d_kp = 1; break;
		case SDLK_j:	all_current_events.j_kp = 1; break;
		case SDLK_f:	all_current_events.f_kp = 1; break;
		case SDLK_y:	all_current_events.y_kp = 1; break;
		case SDLK_o:	all_current_events.o_kp = 1; break;
		case SDLK_p:	all_current_events.p_kp = 1; break;
		case SDLK_s:	all_current_events.s_kp = 1; break;
		case SDLK_n:	all_current_events.n_kp = 1; break;
		
		case SDLK_LEFT:	all_current_events.arrow_left_kp = 1; break;
		case SDLK_RIGHT:all_current_events.arrow_right_kp= 1; break;
		case SDLK_UP:	all_current_events.arrow_up_kp	 = 1; break;
		case SDLK_DOWN:	all_current_events.arrow_down_kp = 1; break;
		case SDLK_RETURN:all_current_events.return_kp    = 1; break;
		
		default:	break;
		}
	}
}

all_events_status events_get_all()
{	int i;
	SDL_Event event;

	events_kp_init();
	while( SDL_PollEvent( &event ) ) 
	{	switch( event.type )
		{case SDL_KEYDOWN:
			handle_key( event.key.keysym.sym,1 );
			any_key_pressed=1;
			break;
		case SDL_KEYUP:
			handle_key( event.key.keysym.sym,0 );
			any_key_pressed=0;
			break;
		case SDL_JOYAXISMOTION:
			if(event.jaxis.axis == 0) /* horizontal */
			{	if(event.jaxis.value<0)
				{	handle_key( key_config[MIK_LEFT].key , 1 );
					handle_key( key_config[MIK_RIGHT].key, 0 );
					any_key_pressed=1;
				}
				else if(event.jaxis.value>0)
				{	handle_key( key_config[MIK_LEFT].key , 0 );
					handle_key( key_config[MIK_RIGHT].key, 1 );
					any_key_pressed=1;
				}
				else
				{	handle_key( key_config[MIK_LEFT].key , 0 );
					handle_key( key_config[MIK_RIGHT].key, 0 );
					any_key_pressed=0;
				}
			}
			if(event.jaxis.axis == 1) /* vertical */
			{	if(event.jaxis.value<0)
				{	handle_key( key_config[MIK_UP].key, 1 );
					handle_key( key_config[MIK_DOWN].key, 0 );
					any_key_pressed=1;
				}
				else if(event.jaxis.value>0)
				{	handle_key( key_config[MIK_UP].key, 0 );
					handle_key( key_config[MIK_DOWN].key, 1 );
					any_key_pressed=1;
				}
				else
				{	handle_key( key_config[MIK_UP].key, 0 );
					handle_key( key_config[MIK_DOWN].key, 0 );
					any_key_pressed=0;
				}
			}
			break;
		case SDL_JOYBUTTONDOWN:
			for(i=0;i<sizeof(key_config)/sizeof(key_config[0]);i++)
			{	if(key_config[i].joycode == event.jbutton.button)
					handle_key( key_config[i].key,1);
			}
			any_key_pressed=1;
			break;
		case SDL_JOYBUTTONUP:
			for(i=0;i<sizeof(key_config)/sizeof(key_config[0]);i++)
			{	if(key_config[i].joycode == event.jbutton.button)
					handle_key( key_config[i].key,0);
			}
			any_key_pressed=0;
			break;
		case SDL_QUIT:
			all_current_events.quit=1;
			break;
	    }
	}
	return all_current_events;
}

int any_event_found(void)
{	events_get_all();
	return any_key_pressed;
}

myList * get_current_config(void)
{	myList * retour = InitList();
	key_config_desc value;
	int i;

	if(!retour)
		return NULL;

	for(i=0;i<sizeof(key_config)/sizeof(key_config[0]);i++)
	{	value.key=key_config[i].key;
		value.txt_key=SDL_GetKeyName(key_config[i].key);
		value.joycode=key_config[i].joycode;
		value.txt_id=key_config[i].txt_id;
		AddToList(retour,&value,sizeof(key_config_desc));
	}
	return retour;
}

void change_key_config(int pos)
{	SDL_Event event;

	assert(pos<sizeof(key_config)/sizeof(key_config[0]));

	while( SDL_WaitEvent( &event ) )
		if( event.type == SDL_KEYDOWN )
		{	key_config[pos].key = event.key.keysym.sym;
			break;
		}
}

void change_joy_config(int pos)
{	SDL_Event event;

	assert(pos<sizeof(key_config)/sizeof(key_config[0]));

	while( SDL_WaitEvent( &event ) )
		if( event.type == SDL_JOYBUTTONDOWN )
		{	key_config[pos].joycode = event.jbutton.button;
			break;
		}
}

int save_keyconfig()
{	int i;
	FILE * fd;
	char * tmp_ch;

	tmp_ch=get_config_directory(KEYCONFIG_FILE);
	fd=fopen(tmp_ch,"w");
	if(!fd)
	{	perror(tmp_ch);
		free(tmp_ch);
		return EXIT_FAILURE;
	}
	free(tmp_ch);
	for(i=0;i<sizeof(key_config)/sizeof(key_config[0]);i++)
		fprintf(fd,"%s \t %d \t %d\n",
			key_config[i].txt_id,key_config[i].key,key_config[i].joycode);
	fclose(fd);
	return EXIT_SUCCESS;
}

int load_keyconfig()
{	int key,joy,i;
	FILE * fd;
	char * tmp_ch;
	char buffer[256];

	tmp_ch=get_config_directory(KEYCONFIG_FILE);
	fd=fopen(tmp_ch,"r");
	if(!fd)
	{	perror(tmp_ch);
		free(tmp_ch);
		return EXIT_FAILURE;
	}
	free(tmp_ch);
	
	joy=-1;
	while(fscanf(fd,"%255s %d %d",buffer,&key,&joy)>=2)
	{	for(i=0;i<sizeof(key_config)/sizeof(key_config[0]);i++)
		{	if(strcmp(key_config[i].txt_id,buffer)==0)
			{	key_config[i].key=key;
				if(joy!=-1)
					key_config[i].joycode=joy;
				break;
			}
		}
		joy=-1;
	}
	return EXIT_SUCCESS;
}

/* joystick */
static SDL_Joystick *js=NULL;
int open_joystick()
{	if( SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1 
	 && SDL_NumJoysticks()
	 && (js=SDL_JoystickOpen(0)) )
		return EXIT_SUCCESS;
	return EXIT_FAILURE;
}

int test_joystick()
{	return (js && SDL_WasInit(SDL_INIT_JOYSTICK) && SDL_JoystickOpened(0));
}

void close_joystick()
{	if(test_joystick())
		SDL_JoystickClose(js);
}
