#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include "lpt_parser.h"
#include "parser.h"
#include "sdl.h"
#include "interface.h"
#include "input.h"

void AddOption(TTF_Font *font, APP *app, TEXT text, const int bttn_num, const int opt_value, const int flag) {
	AddPseudoButton(app, text, bttn_num);


	/* Create texture for value */
	char str[16];
	if (flag == 1)
		snprintf(str, sizeof(str), "%s", (opt_value) ? "Y" : "N");

	else if (flag == 2)
		snprintf(str, sizeof(str), "%d%%", opt_value);

	else
		snprintf(str, sizeof(str), "%d", opt_value);

	TEXT value;
	memset(&value, 0, sizeof(value));

	PrintText(font, app, &value, str);
	if (value.init == 0)
		return;


	/* Print it */
	int rect_x = APPROX2ORIG(app->scr_width, -0.8);
	SDL_Rect rect = {
		.x =  app->scr_width - rect_x - value.w - 20,
		.y = APPROX2ORIG(app->scr_height, (0.75 - (0.2 * bttn_num))),
		.w = value.w + 20,
		.h = 45
	};

	SDL_RenderCopy(app->render, value.texture, NULL, &rect);
	SDL_DestroyTexture(value.texture);
}

int main_menu(APP *app, FONTS *fonts, CONFIG *cfg) {
	char run = 1;
	char mode = IN_MENU;
	size_t index = 0;
	int *value = NULL;
	char changed = 0;



	/* LPT LOGO */
	SDL_Texture *logo = LoadIMG_SDL("files/images/lpt.png", app);
	if (logo == NULL)
		run = -1;



	/* Setup menu text */
	TEXT text_new_game, text_continue, text_settings, text_quit, text_save;
	memset(&text_new_game, 0, sizeof(text_new_game));
	text_continue = text_settings = text_quit = text_save = text_new_game;

	PrintText(fonts->font1, app, &text_new_game, "[n] New Game");
	PrintText(fonts->font1, app, &text_continue, "[c] Continue");
	PrintText(fonts->font1, app, &text_settings, "[s] Settings");
	PrintText(fonts->font1, app, &text_save, "[k] Save");
	PrintText(fonts->font1, app, &text_quit, "[q] Quit");

	TEXT menu_msgs[] = {text_quit, text_settings, text_new_game, text_save, text_continue};
	size_t menu_size = sizeof(menu_msgs) / sizeof(TEXT);
	if (TextArray(menu_msgs, menu_size, TEXT_ARRAY_SCAN))
		run = -1;



	/* Setup settings text */
	TEXT settings, fullscreen, fullscreen_custom, vsync, sound_vol, music_vol, screen_h, screen_w, pointer, text_back;
	memset(&settings, 0, sizeof(settings));
	fullscreen = fullscreen_custom = vsync = sound_vol = music_vol = screen_h = screen_w = pointer = text_back = settings;

	PrintText(fonts->font1, app, &fullscreen, "Fullscreen mode:");
	PrintText(fonts->font1, app, &fullscreen_custom, "Custom resolution for fullscreen: Y");
	PrintText(fonts->font1, app, &vsync, "VSync:");
	PrintText(fonts->font1, app, &sound_vol, "Sound volume:");
	PrintText(fonts->font1, app, &music_vol, "Music volume:");
	PrintText(fonts->font1, app, &screen_h, "Screen height:");
	PrintText(fonts->font1, app, &screen_w, "Screen width:");
	PrintText(fonts->font1, app, &text_back, "[q] Back");
	PrintText(fonts->font1, app, &settings, "[settings] Restart requied...");
	PrintText(fonts->font2, app, &pointer, ">");

	TEXT settings_msgs[] = {fullscreen, fullscreen_custom, vsync, sound_vol, music_vol, screen_h, screen_w, text_save, text_back, pointer, settings};
	int *settings_opt[] = {&cfg->fullscreen, &cfg->fullscreen_custom, &cfg->vsync, &cfg->sound_volume, &cfg->music_volume, &cfg->screen_h, &cfg->screen_w};
	size_t settings_size = sizeof(settings_msgs) / sizeof(TEXT);
	if (TextArray(settings_msgs, settings_size, TEXT_ARRAY_SCAN))
		run = -1;



	/* Game loop */
	while (run > 0) {
		if (value == NULL)
			value = settings_opt[1];


		/* Input and navigation */
		int status = Input(app, &run, fonts, mode);
		switch (status) {
			case SETTINGS:
				mode = IN_SETTINGS;
				break;

			case KEY_DOWN:
				if (index > 0) {
					index--;
					value = settings_opt[index];
				}

				break;

			case KEY_UP:
				if (index < settings_size - 5) {
					index++;
					value = settings_opt[index];
				}

				break;

			case KEY_LEFT:
				changed = 1;
				if ((value == &cfg->screen_w && *value > 639) || (value == &cfg->screen_h && *value > 479))
					(*value)--;

				else if (*value > 0)
					(*value)--;

				break;

			case KEY_RIGHT:
				changed = 1;
				if (value == &cfg->fullscreen || value == &cfg->fullscreen_custom || value == &cfg->vsync)
					*value = 1;

				else if ((value == &cfg->music_volume && *value < 100) || (value == &cfg->sound_volume && *value < 100))
					(*value) += 2;

				else if (value == &cfg->screen_w || value == &cfg->screen_h)
					(*value) += 5;

				break;

			case SAVE:
				changed = 0;
				if (WriteCfg(*cfg))
					run = -1;
				break;

			case NEW_GAME:
				cfg->saved_scene = 0;
				/* fallthrough */

			case CONTINUE:
				char game_run = 1;
				while (game_run > 0) {
					game_run = lpt_parser(app, fonts, cfg);
					if (game_run == ERROR) {
						run = -1;
						break;
					}

					else if (game_run == MENU)
						break;

					else if (game_run == LPTP_NORMAL)
						cfg->saved_scene++;

					else if (game_run == ENDGAME) {
						cfg->saved_scene = 0;
						break;
					}
				}

				break;

			default:
				break;
		}


		/* Background */
		SDL_SetRenderDrawColor(app->render, 0xFF, 0xFF, 0xFF, 0xFF);
		SDL_RenderClear(app->render);


		/* Create GUI */
		if (mode == IN_MENU) {
			/* Logo */
			SDL_Rect rect = {
				.x = APPROX2ORIG(app->scr_width, -0.5),
				.y = APPROX2ORIG(app->scr_height, -0.5),
				.w = 128 * 2,
				.h = 64 * 2
			};

			SDL_RenderCopy(app->render, logo, NULL, &rect);

			/* Menu */
			size_t i;
			for (i = 0; i < menu_size - 1; i++)
				AddPseudoButton(app, menu_msgs[i], i);

			if (cfg->saved_scene > 0)
				AddPseudoButton(app, menu_msgs[i], i);
		}

		else if (mode == IN_SETTINGS) {
			/* Menu */
			AddOption(fonts->font1, app, fullscreen,        0, cfg->fullscreen, 1);
			AddOption(fonts->font1, app, fullscreen_custom, 1, cfg->fullscreen_custom, 1);
			AddOption(fonts->font1, app, vsync,             2, cfg->vsync, 1);
			AddOption(fonts->font1, app, sound_vol,         3, cfg->sound_volume, 2);
			AddOption(fonts->font1, app, music_vol,         4, cfg->music_volume, 2);
			AddOption(fonts->font1, app, screen_h,          5, cfg->screen_h, 0);
			AddOption(fonts->font1, app, screen_w,          6, cfg->screen_w, 0);
			AddPseudoButton(app, text_back, 7);

			if (changed)
				AddPseudoButton(app, text_save, 8);

			/* Pointer */
			SDL_Rect rect = {
				.x = 0,
				.y = APPROX2ORIG(app->scr_height, (0.75 - (0.2 * index))),
				.w = pointer.w,
				.h = pointer.h
			};

			SDL_RenderCopy(app->render, pointer.texture, NULL, &rect);

			/* Title */
			rect.y = 0;
			rect.w = settings.w;
			rect.h = settings.h;
			SDL_RenderCopy(app->render, settings.texture, NULL, &rect);
		}

		if (run == 0 && mode == IN_SETTINGS) {
			mode = IN_MENU;
			run = 1;
		}


		/* Render */
		SDL_RenderPresent(app->render);
		SDL_Delay(20);
	}



	/* Free structures */
	if (logo)
		SDL_DestroyTexture(logo);

	TextArray(menu_msgs, menu_size, TEXT_ARRAY_FREE);
	TextArray(settings_msgs, menu_size, TEXT_ARRAY_FREE);
	return (run == -1) ? 1 : 0;
}

int main(void) {
	/* Config */
	CONFIG cfg = {
		.fullscreen = 1,
		.fullscreen_custom = 0,
		.screen_w = 480,
		.screen_h = 640,
		.sound_volume = 100,
		.music_volume = 20,
		.vsync = 0,
	};

	if (access(CONFIG_FILE, R_OK) < 0) {
		fprintf(stderr, "Failed to open %s: %s. Creating...\n", CONFIG_FILE, strerror(errno));
		WriteCfg(cfg);
	}

	else
		ReadCfg(&cfg);

	/* Init SDL */
	APP app;
	if (Init_SDL(cfg, &app))
		return 1;

	int ret = 0;

	FONTS fonts;
	if (InitFonts(&fonts, app))
		ret = 1;

	/* Game loop*/
	if (!ret)
		ret = main_menu(&app, &fonts, &cfg);

	/* Clean up */
	CloseFonts(&fonts);
	CleanUp_SDL(&app);
	if (ret)
		fputs("Game returned 1: interal error\n", stderr);

	fputs("Thanks for playing\n", stderr);
	return ret;
}
