/* Bob */

#include "main.h"
#include "menu.h"
#include "menuproc.h"
#include "m_game.h"
#include "zcontrol.h"
#include "options.h"
#include "game.h"
#include "m_main.h"
#include "m_game.h"
#include "m_ctrl.h"
#include "level.h"
#include "preview.h"
#include "log.h"
#include "timeloop.h"
#include "sound2.h"

void md_control_conf(BITMAP *bmp, BOMB_MENU *entry, int seleted);
void md_level_select(BITMAP *bmp, BOMB_MENU *entry, int selected);
int mk_level_option(BOMB_MENU *entry, int k);
int mk_controler_option(BOMB_MENU *entry, int k);



typedef struct CONTROL_CONF {
	BITMAP *image;
	char *text;
	int type;
	int (*config_proc)(int player_id, int type);
} CONTROL_CONF;

typedef struct CONTROL_CONF2 {
	CONTROL_CONF *control;
	int flip_time[N_PLAYERS];
	int flip_dir[N_PLAYERS];
} CONTROL_CONF2;


int mkc_game_menu() {

	int red = makecol(255, 0, 0);
	int white = makecol(255, 255, 255);
	int green = makecol(0, 255, 0);
	int blue = makecol(0, 0, 255);
	int preview_size[] = {200, 200};

	const char *menu_title =       translate("MakeYourGame");
	const char *txt_choose_level = translate("Level");
	const char *txt_play =         translate("PlayForGreatJustice");
	const char *txt_return =       translate("MainScreenReturnOn");

	CONTROL_CONF *device_array = malloc(sizeof(CONTROL_CONF) * NumControlDevices);
	CONTROL_CONF2 device_array2 = {device_array, {0, 0, 0, 0}, {0, 0, 0, 0}};

	BOMB_MENU game_menu[] = {
		/* option draw            x    y      d                dp               dp2                   key          k  k2              kp */
		{ 0, &md_text_centre,   320,  10, white,         (char*)menu_title, 0,                     0,           0, 0,              0},

		{ 0, &md_text_right ,   100,  60,  blue,            player_name[0], 0,                     0,           0,                 0, 0},
		{ 1, &md_control_conf,  110,  38, white, &player_control_device[0],&device_array2,&mk_controler_option, 0, NumControlDevices, &player_control_device[0]},

		{ 0, &md_text_right ,   100, 142,  blue,            player_name[1], 0,                     0,           0,                 0, 0},
		{ 1, &md_control_conf,  110, 120, white, &player_control_device[1],&device_array2,&mk_controler_option, 1, NumControlDevices, &player_control_device[1]},

		{ 0, &md_text_right ,   100, 224,  blue,            player_name[2], 0,                     0,           0,                 0, 0},
		{ 1, &md_control_conf,  110, 202, white, &player_control_device[2],&device_array2,&mk_controler_option, 2, NumControlDevices, &player_control_device[2]},

		{ 0, &md_text_right ,   100, 306,  blue,            player_name[3], 0,                     0,           0,                 0, 0},
		{ 1, &md_control_conf,  110, 284, white, &player_control_device[3],&device_array2,&mk_controler_option, 3, NumControlDevices, &player_control_device[3]},

		{ 1, &md_level_select,  160, 406, white, (char*)txt_choose_level,    &chosen_level, &mk_level_option,  0, n_levels,       &chosen_level},

		{ 0, &md_preview,       370, 100, 0,            preview_size,        &chosen_level,        0,           0, 0,              0           },

        { 1, &md_text_centre,   320, 430, green,          (char*)txt_play,   0               , &mk_command, 0, 0             , &mkc_play_game  },
        { 1, &md_text_centre,   320, 460, red,          (char*)txt_return,   0               , &mk_command, 0, 0             , &mkc_exit   },
		{ 0, 0              ,     0,   0,            0, 0                 ,  0               , 0          , 0, 0             , 0           }
	};

	int i;

    if (!device_array) exit(37);

	for (i = 0; i < NumControlDevices; i++) {
		if (ControlDeviceType[i] == CONTROL_TYPE_KEYBOARD) {
			device_array[i].config_proc = mkc_config_controls;
			device_array[i].image = Controler[2];
		}
		else if (ControlDeviceType[i] == CONTROL_TYPE_JOYSTICK) {
			device_array[i].config_proc = mkc_config_controls;
			device_array[i].image = Controler[3];
		}
		else if (ControlDeviceType[i] == CONTROL_TYPE_ZIG_AI) {
			device_array[i].config_proc = NULL; /*mkc_config_ai; */
			device_array[i].image = Controler[1];
		}
		else {
			device_array[i].config_proc = NULL;
			device_array[i].image = Controler[0];
		}
		device_array[i].text = ControlDeviceName[i];
		device_array[i].type = ControlDeviceType[i];
	}

	run_bomb_menu(game_menu, 9);

	free(device_array);

    return 0;
}

/* mk_level_option().
   kp points to the option in question (an int).
   k2 represents the number of values for this option.
   The left and right arrows will change the value, keeping it within the
   range 0 to k2-1.
   mkc_play_game() will be called on enter or space.
*/
int mk_level_option(BOMB_MENU *entry, int k) {

	switch (k >> 8) {

		case KEY_LEFT:
			(*(int *)entry->kp)--;
			if (*(int *)entry->kp < 0) 
				*(int *)entry->kp += entry->k2;
			play_sound(Sample.MenuBeep1, 0, 0, 0, 255, 1000, FALSE);
			break;

		case KEY_RIGHT:
			(*(int *)entry->kp)++;
			if (*(int *)entry->kp >= entry->k2) 
				*(int *)entry->kp = 0;
			play_sound(Sample.MenuBeep1, 0, 0, 0, 255, 1000, FALSE);
			break;

		case KEY_SPACE:
		case KEY_ENTER:
			play_sound(Sample.MenuBeep2, 0, 0, 0, 255, 1000, FALSE);
			return mkc_play_game();
	}

	return 0;
}



static int shift_playing_voice = -1;

/* mk_controler_option().
   kp points to the option in question (an int).
   k2 represents the number of values for this option.
   The left and right arrows will change the value, keeping it within the
   range 0 to k2-1.
   dp2 MUST point to the CONTORL_CONF array
   The control->config_proc function will be called on enter or space.
   k will contain the player_id.
*/
int mk_controler_option(BOMB_MENU *entry, int k) {

	CONTROL_CONF2 *conf = entry->dp2;
	CONTROL_CONF *control = &(conf->control[*((int*)entry->kp)]);

	switch (k >> 8) {

		case KEY_LEFT:
			(*(int *)entry->kp)--;
			if (*(int *)entry->kp < 0)
				*(int *)entry->kp += entry->k2;
			
			conf->flip_time[entry->k] = game_time;
			conf->flip_dir[entry->k]  = 1;
			
			if (shift_playing_voice != -1)
				deallocate_voice(shift_playing_voice);
			shift_playing_voice = play_sound(Sample.Shift, 0, 0, 0, 255, 1000, FALSE);
			break;

		case KEY_RIGHT:
			(*(int *)entry->kp)++;
			if (*(int *)entry->kp >= entry->k2)
				*(int *)entry->kp = 0;
			
			conf->flip_time[entry->k] = game_time;
			conf->flip_dir[entry->k]  = -1;
			
			if (shift_playing_voice != -1)
				deallocate_voice(shift_playing_voice);
			shift_playing_voice = play_sound(Sample.Shift, 0, 0, 0, 255, 1000, FALSE);
			break;

		case KEY_SPACE:
		case KEY_ENTER:
			{		  
				if (control->config_proc) {
					play_sound(Sample.MenuBeep2, 0, 0, 0, 255, 1000, FALSE);
					return (*control->config_proc)(entry->k, control->type);
				}
				else
					play_sound(Sample.Error, 0, 0, 0, 255, 1000, FALSE);
			}
			break;
	}

	return 0;
}


/* md_control_image(): this determines the player's control type using
   player_control_type[d] along with ControlDeviceType[]. The latter is
   declared in control.h. Then, if the type is nonzero, it looks up a
   datafile index in control_image_id[] and draws the datafile object with
   draw_sprite().
*/
void md_control_image(BITMAP *bmp, BOMB_MENU *entry, int selected) {

	BITMAP *src = ((BITMAP **)entry->dp2) [*(int *)entry->dp];
	masked_blit(src, bmp, 0, 0, entry->x, entry->y, src->w, src->h);
	rect(bmp, entry->x - 2, entry->y - 2, entry->x + src->w + 1, entry->y + src->h + 1,
		selected ? makecol(255, 255, 0) : makecol(0, 0, 0));

	return;
}


void md_control_conf(BITMAP *bmp, BOMB_MENU *entry, int selected) {

	CONTROL_CONF2 *conf = entry->dp2;
	CONTROL_CONF *control = &(conf->control[*((int*)entry->dp)]);
	CONTROL_CONF *prev_control = &(conf->control[((*((int*)entry->dp) - 1) < 0) ? entry->k2 - 1 : *((int*)entry->dp) - 1]);
	CONTROL_CONF *next_control = &(conf->control[((*((int*)entry->dp) + 1) >= entry->k2) ? 0   : *((int*)entry->dp) + 1]);
	int i;
	RGB pod_colors[N_PLAYERS] = {
		{0, 0, 255, 0},
		{255, 0, 0, 0},
		{255, 255, 0, 0},
		{0, 255, 0, 0}
	};

	/* Draw the controlers */
	if (control->image) {
		int offs = (game_time - conf->flip_time[entry->k]) * 6;
		int w = control->image->w, h = control->image->h;

		int y2 = entry->y + h + text_height(MenuFont);

		for (i = entry->y; i < y2; i++) {
			hline(bmp, entry->x, i, entry->x + w * 2 + 32,
				makecol(pod_colors[entry->k].r ? (255 - pod_colors[entry->k].r * (i - entry->y) / (y2 - entry->y) / 2) : 0,
				pod_colors[entry->k].g ? 255 - pod_colors[entry->k].g * (i - entry->y) / (y2 - entry->y) / 2 : 0,
				pod_colors[entry->k].b ? 255 - pod_colors[entry->k].b * (i - entry->y) / (y2 - entry->y) / 2 : 0));
		}

		if (!conf->flip_time[entry->k])
			offs = -1;

		set_clip(bmp, entry->x + 16 + w / 6, entry->y, entry->x + 16 + w * 11 / 6, entry->y + h - 1);

		if (offs != -1 && conf->flip_dir[entry->k] == -1) {

			/* cur->prev */
			masked_blit(prev_control->image, bmp, 0, 0, entry->x + 16 + w / 2 - w * offs / 100, entry->y, w, h);
			/* next->cur */
			masked_blit(control->image, bmp, 0, 0, entry->x + w * 3 / 2 - w * offs / 100 + 16, entry->y, w, h);
			/* next_next->next */
			masked_blit(next_control->image, bmp, 0, 0, entry->x + 16 + w * 5 / 2 - w * offs / 100, entry->y, w, h);
		}
		else if (offs != -1 && conf->flip_dir[entry->k] == 1) {

			/* prev_prev -> prev */
			masked_blit(prev_control->image, bmp, 0, 0, entry->x + 16 - w * 3 / 2 + w * offs / 100, entry->y, w, h);
			/* prev->cur */
			masked_blit(control->image, bmp, 0, 0, entry->x + 16 - w / 2 + w * offs / 100, entry->y, w, h);
			/* cur->next */
			masked_blit(next_control->image, bmp, 0, 0, entry->x + w / 2 + w * offs / 100 + 16, entry->y, w, h);
		}
		else {
			masked_blit(control->image, bmp, 0, 0, entry->x + w / 2 + 16, entry->y, w, h);
			masked_blit(prev_control->image, bmp, 0, 0, entry->x + 16 - w / 2, entry->y, w, h);		
			masked_blit(next_control->image, bmp, 0, 0, entry->x + w * 3 / 2 + 16, 	entry->y, w, h);
		}
		set_clip(bmp, 0, 0, bmp->w - 1, bmp->h - 1);

		if (offs >= 100 || offs < 0)
			conf->flip_time[entry->k] = 0;

		if (selected)
			rect(bmp, entry->x + 18, entry->y, entry->x + 2 * control->image->w + 14, entry->y + control->image->h + text_height(MenuFont) / 2, makecol(255, 255, 0));

		/* Draw arrows */
		masked_blit(LeftArrow,  bmp, 0, 0, entry->x, entry->y + (control->image->h - 32) / 2, LeftArrow->w, LeftArrow->h);
		masked_blit(RightArrow, bmp, 0, 0, entry->x + 16 + control->image->w * 2, entry->y + (control->image->h - 32) / 2, RightArrow->w, RightArrow->h);
	}
	

	/* Erase old controlner name */
	if (control->image) {
		/* Write the controler name */
		textout_centre(bmp, MenuFont, control->text, entry->x + control->image->w + 16, entry->y + control->image->h - 2, entry->d);
	}
}


void md_level_select(BITMAP *bmp, BOMB_MENU *entry, int selected) {

	int max_w = 0, i;

	textout_right(bmp, MenuFont, entry->dp, entry->x, entry->y - text_height(MenuFont) - 6, entry->d);
	textprintf(bmp, MenuFont, entry->x, entry->y - text_height(MenuFont) - 6, entry->d, 
		"%4i/%i", (*((int*)entry->dp2)) + 1, entry->k2);
	textout(bmp, MenuFont, the_level_names[*((int*)entry->dp2)], entry->x + 10, entry->y, makecol(255, 255, 255));

	for (i = 0; i < entry->k2; i++)
		max_w = MAX(max_w, text_length(MenuFont, the_level_names[i]));

	masked_blit(LeftArrow,  bmp, 0, 0, entry->x - LeftArrow->w, entry->y + (text_height(MenuFont) - LeftArrow->h) / 2, LeftArrow->w, LeftArrow->h);
	masked_blit(RightArrow, bmp, 0, 0, entry->x + max_w + RightArrow->w + 10,
		entry->y + (text_height(MenuFont) - RightArrow->h) / 2, RightArrow->w, RightArrow->h);

	if (selected)
		rect(bmp, entry->x + 5, entry->y - 2, entry->x + max_w + 15,
			entry->y + text_height(MenuFont) + 2, makecol(255, 255, 0));
}
