#include "param.h"
#include <fstream>	// for char_traits, basic_ostream, basic_ifstream, basi...
#include <iostream> // for cout
#include "utils.h"	// for Param, ParamGame, Zone, ParamBalloon

Param param;

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

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

// 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.game_area.rect = {0, 0, param.game.width, param.game.height};
	param.game.play_area.rect = {0, 0, param.game.width, 216};
	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 = {255, 255, 255};
	param.background.attenuate_alpha = 32;

	// BALLOONS
	param.balloon_1.vel = 2.60f;
	param.balloon_1.grav = 0.09f;
	param.balloon_2.vel = 3.50f;
	param.balloon_2.grav = 0.10f;
	param.balloon_3.vel = 4.50f;
	param.balloon_3.grav = 0.10f;
	param.balloon_4.vel = 4.95f;
	param.balloon_4.grav = 0.10f;
}

// Establece valores para los parametros a partir de un fichero de texto
void loadParamsFromFile(std::string filePath)
{
	// Pone valores por defecto a las variables
	initParam();

	// Variables para manejar el fichero
	std::ifstream file(filePath);
	std::string line;
	std::string param1;
	std::string param2;

	// Si el fichero se puede abrir
	if (file.good())
	{
#ifdef VERBOSE
		const std::string filename = filePath.substr(filePath.find_last_of("\\/") + 1);
		std::cout << "Reading file: " << filename << std::endl;
#endif
		// Procesa cada linea del fichero
		while (std::getline(file, line))
		{
			// Reinicia variables
			param1 = "";
			param2 = "";

			// Elimina los comentarios
			line = line.substr(0, line.find("#"));

			// Ignora los espacios en blanco
			int pos = 0;
			while (pos < (int)line.size() && (int)line[pos] <= 32)
			{
				pos++;
			}

			// Si no ha llegado al final de la linea, es que hay algo escrito (no es una linea vacía)
			if (pos < (int)line.size())
			{
				// Elimina el espacio en blanco
				line = line.substr(pos, std::string::npos);

				// Se queda con todo lo que no sean espacios en blanco
				pos = 1;
				while (pos <= (int)line.size() && (int)line[pos] > 32)
				{
					pos++;
				}

				// Si llega al final de la linea, falta la segunda palabra
				if (pos < (int)line.size())
				{
					// Se queda con la primera palabra
					param1 = line.substr(0, pos);

					// Y recorta la linea
					line = line.substr(pos, std::string::npos);

					// Ignora los espacios en blanco
					pos = 0;
					while (pos <= (int)line.size() && (int)line[pos] <= 32)
					{
						pos++;
					}

					// Si llega al final de la linea, falta la segunda palabra
					if (pos < (int)line.size())
					{
						// Elimina el espacio en blanco
						line = line.substr(pos, std::string::npos);

						// Ignora los espacios en blanco
						pos = 1;
						while (pos <= (int)line.size() && (int)line[pos] > 32)
						{
							pos++;
						}
						// Se queda con la segunda palabra
						param2 = line.substr(0, pos);
					}
				}
			}

			setParams(param1, param2);
		}

		// Cierra el fichero
		file.close();
	}
#ifdef VERBOSE
	else
		std::cout << "Failed to load file: " << filePath << std::endl;
#endif

	precalculateZones();
}

// Asigna variables a partir de dos cadenas
bool setParams(std::string var, std::string value)
{
	// Indicador de éxito en la asignación
	bool 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.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);
	}

	// 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_1.vel = std::stof(value);
	}

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

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

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

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

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

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

	else if (var == "balloon_4.grav")
	{
		param.balloon_4.grav = std::stof(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;
}