#include "param.h"
#include <SDL3/SDL_log.h> // Para SDL_LogCategory, SDL_LogError, SDL_LogInfo
#include <fstream>		  // Para basic_istream, basic_ifstream, ifstream
#include <sstream>		  // Para basic_istringstream
#include <stdexcept>	  // Para runtime_error
#include <string>		  // Para operator==, stoi, char_traits, string, ope...
#include "utils.h"		  // Para Zone, Color, NotifyPosition, getFileName

Param param;

// Calcula variables a partir de otras variables
void precalculateZones();

// Asigna variables a partir de dos cadenas
bool setParams(const std::string &var, const std::string &value);

// Establece valores por defecto a las variables
void initParam()
{
	// GAME
	param.game.width = 320;
	param.game.height = 256;
	param.game.item_size = 20;
	param.game.coffee_machine_w = 28;
	param.game.coffee_machine_h = 37;
	param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
	param.game.play_area.rect = {0, 0, param.game.width, 216};
	param.game.enter_name_seconds = 30;
	param.game.speed = 15;
	precalculateZones();

	// SCOREBOARD
	param.scoreboard = {0, 216, param.game.width, 40};

	// FADE
	param.fade.num_squares_width = param.game.width / 2;
	param.fade.num_squares_height = param.game.height / 2;
	param.fade.random_squares_delay = 1;
	param.fade.random_squares_mult = 500;
	param.fade.post_duration = 80;
	param.fade.venetian_size = 16;

	// TITLE
	param.title.press_start_position = 160;
	param.title.title_duration = 800;
	param.title.arcade_edition_position = 123;
	param.title.title_c_c_position = 11;

	// BACKGROUND
	param.background.attenuate_color = Color(255, 255, 255);
	param.background.attenuate_alpha = 32;

	// BALLOONS
	param.balloon.emplace_back(0.09f, 2.60f);
	param.balloon.emplace_back(0.10f, 3.50f);
	param.balloon.emplace_back(0.10f, 4.50f);
	param.balloon.emplace_back(0.10f, 4.95f);

	// NOTIFICATION
	param.notification.pos_v = NotifyPosition::TOP;
	param.notification.pos_h = NotifyPosition::LEFT;
	param.notification.sound = false;
	param.notification.color.r = 48;
	param.notification.color.g = 48;
	param.notification.color.b = 48;
}

// Carga los parámetros desde un archivo
void loadParamsFromFile(const std::string &file_path)
{
	// Inicializa los parámetros con valores por defecto
	initParam();

	// Abre el archivo
	std::ifstream file(file_path);
	if (!file.is_open())
	{
		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo abrir el archivo %s", file_path.c_str());
		throw std::runtime_error("No se pudo abrir el archivo: " + file_path);
	}

	SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nReading file: %s", getFileName(file_path).c_str());

	std::string line, param1, param2;
	while (std::getline(file, line))
	{
		// Elimina comentarios
		auto comment_pos = line.find('#');
		if (comment_pos != std::string::npos)
		{
			line.resize(comment_pos);
		}

		// Usa un stream para separar palabras
		std::istringstream iss(line);
		if (iss >> param1 >> param2)
		{
			if (!setParams(param1, param2))
			{
				SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Parámetro desconocido: %s", param1.c_str());
			}
		}
	}

	// Cierra el archivo
	file.close();

	// Realiza cálculos adicionales después de cargar los parámetros
	precalculateZones();
}

// Asigna variables a partir de dos cadenas
bool setParams(const std::string &var, const std::string &value)
{
	// Indicador de éxito en la asignación
	auto success = true;

	// GAME
	if (var == "game.width")
	{
		param.game.width = std::stoi(value);
	}

	else if (var == "game.height")
	{
		param.game.height = std::stoi(value);
	}

	else if (var == "game.item_size")
	{
		param.game.item_size = std::stoi(value);
	}

	else if (var == "game.coffee_machine_w")
	{
		param.game.coffee_machine_w = std::stoi(value);
	}

	else if (var == "game.coffee_machine_h")
	{
		param.game.coffee_machine_h = std::stoi(value);
	}

	else if (var == "game.play_area.rect.x")
	{
		param.game.play_area.rect.x = std::stoi(value);
	}

	else if (var == "game.play_area.rect.y")
	{
		param.game.play_area.rect.y = std::stoi(value);
	}

	else if (var == "game.play_area.rect.w")
	{
		param.game.play_area.rect.w = std::stoi(value);
	}

	else if (var == "game.play_area.rect.h")
	{
		param.game.play_area.rect.h = std::stoi(value);
	}

	else if (var == "game.enter_name_seconds")
	{
		param.game.enter_name_seconds = std::stoi(value);
	}

	// FADE
	else if (var == "fade.num_squares_width")
	{
		param.fade.num_squares_width = std::stoi(value);
	}

	else if (var == "fade.num_squares_height")
	{
		param.fade.num_squares_height = std::stoi(value);
	}

	else if (var == "fade.random_squares_delay")
	{
		param.fade.random_squares_delay = std::stoi(value);
	}

	else if (var == "fade.random_squares_mult")
	{
		param.fade.random_squares_mult = std::stoi(value);
	}

	else if (var == "fade.post_duration")
	{
		param.fade.post_duration = std::stoi(value);
	}

	else if (var == "fade.venetian_size")
	{
		param.fade.venetian_size = std::stoi(value);
	}

	// SCOREBOARD
	else if (var == "scoreboard.x")
	{
		param.scoreboard.x = std::stoi(value);
	}

	else if (var == "scoreboard.y")
	{
		param.scoreboard.y = std::stoi(value);
	}

	else if (var == "scoreboard.w")
	{
		param.scoreboard.w = std::stoi(value);
	}

	else if (var == "scoreboard.h")
	{
		param.scoreboard.h = std::stoi(value);
	}

	// TITLE
	else if (var == "title.press_start_position")
	{
		param.title.press_start_position = std::stoi(value);
	}

	else if (var == "title.title_duration")
	{
		param.title.title_duration = std::stoi(value);
	}

	else if (var == "title.arcade_edition_position")
	{
		param.title.arcade_edition_position = std::stoi(value);
	}

	else if (var == "title.title_c_c_position")
	{
		param.title.title_c_c_position = std::stoi(value);
	}

	// BACKGROUND
	else if (var == "background.attenuate_color.r")
	{
		param.background.attenuate_color.r = std::stoi(value);
	}

	else if (var == "background.attenuate_color.g")
	{
		param.background.attenuate_color.g = std::stoi(value);
	}

	else if (var == "background.attenuate_color.b")
	{
		param.background.attenuate_color.b = std::stoi(value);
	}

	else if (var == "background.attenuate_alpha")
	{
		param.background.attenuate_alpha = std::stoi(value);
	}

	// BALLOON
	else if (var == "balloon_1.vel")
	{
		param.balloon.at(0).vel = std::stof(value);
	}

	else if (var == "balloon_1.grav")
	{
		param.balloon.at(0).grav = std::stof(value);
	}

	else if (var == "balloon_2.vel")
	{
		param.balloon.at(1).vel = std::stof(value);
	}

	else if (var == "balloon_2.grav")
	{
		param.balloon.at(1).grav = std::stof(value);
	}

	else if (var == "balloon_3.vel")
	{
		param.balloon.at(2).vel = std::stof(value);
	}

	else if (var == "balloon_3.grav")
	{
		param.balloon.at(2).grav = std::stof(value);
	}

	else if (var == "balloon_4.vel")
	{
		param.balloon.at(3).vel = std::stof(value);
	}

	else if (var == "balloon_4.grav")
	{
		param.balloon.at(3).grav = std::stof(value);
	}

	// NOTIFICACIONES
	else if (var == "notification.pos_h")
	{
		if (value == "LEFT")
		{
			param.notification.pos_h = NotifyPosition::LEFT;
		}
		else if (value == "MIDDLE")
		{
			param.notification.pos_h = NotifyPosition::MIDDLE;
		}
		else
		{
			param.notification.pos_h = NotifyPosition::RIGHT;
		}
	}

	else if (var == "notification.pos_v")
	{
		param.notification.pos_v = value == "TOP" ? NotifyPosition::TOP : NotifyPosition::BOTTOM;
	}

	else if (var == "notification.sound")
	{
		param.notification.sound = stringToBool(value);
	}

	else if (var == "notification.color.r")
	{
		param.notification.color.r = std::stoi(value);
	}

	else if (var == "notification.color.g")
	{
		param.notification.color.g = std::stoi(value);
	}

	else if (var == "notification.color.b")
	{
		param.notification.color.b = std::stoi(value);
	}

	// RESTO
	else
	{
		success = false;
	}

	return success;
}

// Calcula variables a partir de otras variables
void precalculateZones()
{
	// playArea
	param.game.play_area.center_x = param.game.play_area.rect.w / 2;
	param.game.play_area.first_quarter_x = param.game.play_area.rect.w / 4;
	param.game.play_area.third_quarter_x = param.game.play_area.rect.w / 4 * 3;
	param.game.play_area.center_y = param.game.play_area.rect.h / 2;
	param.game.play_area.first_quarter_y = param.game.play_area.rect.h / 4;
	param.game.play_area.third_quarter_y = param.game.play_area.rect.h / 4 * 3;

	// gameArea
	param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
	param.game.game_area.center_x = param.game.game_area.rect.w / 2;
	param.game.game_area.first_quarter_x = param.game.game_area.rect.w / 4;
	param.game.game_area.third_quarter_x = param.game.game_area.rect.w / 4 * 3;
	param.game.game_area.center_y = param.game.game_area.rect.h / 2;
	param.game.game_area.first_quarter_y = param.game.game_area.rect.h / 4;
	param.game.game_area.third_quarter_y = param.game.game_area.rect.h / 4 * 3;
}