use crate::logic::game_board::ModifyMode;

use super::{
	texture_store::TextureStore,
	ui_event::{GUIEvent, GUIEvents},
	Language, UIState,
};
use macroquad::{
	hash,
	prelude::*,
	ui::{root_ui, widgets, Skin, Ui},
};

pub struct SettingsMenu {
	mines: usize,
	width: usize,
	height: usize,
	board_modify_mode: ModifyMode,
}
impl Default for SettingsMenu {
	fn default() -> Self {
		Self {
			mines: 99,
			width: 30,
			height: 16,
			board_modify_mode: ModifyMode::Flag,
		}
	}
}

impl SettingsMenu {
	pub fn render(
		&mut self,
		ui_state: &UIState,
		event_handler: &mut GUIEvents,
		textures: &TextureStore,
		skin: &Skin,
		exit_button_skin: &Skin,
	) {
		let screen_width = screen_width();
		let screen_height = screen_height();
		let background_color = Color::from_rgba(192, 192, 192, 255);

		root_ui().window(hash!(), vec2(0., 0.), vec2(screen_width, screen_height), |ui| {
			draw_rectangle(0f32, 0f32, screen_width, screen_height, background_color);
			ui.push_skin(&exit_button_skin);
			if widgets::Button::new("").size(vec2(50.0, 50.0)).position(vec2(0f32, 0f32)).ui(ui) {
				event_handler.add(GUIEvent::CloseSettings)
			}
			ui.pop_skin();
			ui.push_skin(&skin);
			let half_screen_width = screen_width * 0.5;
			const MIN_MINEFIELD_WIDTH: usize = 5;
			const MAX_MINEFIELD_WIDTH: usize = 100;
			const MIN_MINEFIELD_HEIGHT: usize = 5;
			const MAX_MINEFIELD_HEIGHT: usize = 100;
			render_counter(
				&mut self.width,
				ui,
				&textures,
				vec2(half_screen_width, 100f32),
				String::from("Minefield Width"),
				MIN_MINEFIELD_WIDTH,
				MAX_MINEFIELD_WIDTH,
			);
			render_counter(
				&mut self.height,
				ui,
				&textures,
				vec2(half_screen_width, 200f32),
				String::from("Minefield Height"),
				MIN_MINEFIELD_WIDTH,
				MIN_MINEFIELD_HEIGHT,
			);
			render_counter(
				&mut self.mines,
				ui,
				&textures,
				vec2(half_screen_width, 300f32),
				String::from("Mines"),
				1,
				self.width * self.height - 10,
			);
			const NEW_GAME_HEIGHT: f32 = 40f32;
			const NEW_GAME_WIDTH: f32 = 250f32;
			if widgets::Button::new("New Game")
				.size(vec2(NEW_GAME_WIDTH, NEW_GAME_HEIGHT))
				.position(vec2((screen_width - NEW_GAME_WIDTH) * 0.5, 0.0))
				.ui(ui)
			{
				event_handler.add(GUIEvent::CreateNewGame(self.width, self.height, self.mines));
				event_handler.add(GUIEvent::CloseSettings);
			}
			const BUTTON_MENU_WIDTH: f32 = 250f32;
			let language_button_x = (screen_width - BUTTON_MENU_WIDTH) * 0.5;
			const BUTTON_SIZE: f32 = 100f32;
			const BUTTON_MENU_Y: f32 = 400f32;
			let question_button_x = (screen_width - BUTTON_MENU_WIDTH) * 0.5 + (BUTTON_MENU_WIDTH - BUTTON_SIZE);
			const BUTTON_MENU_LABEL_HEIGHT: f32 = 20f32;
			widgets::Label::new("Language")
				.position(vec2(language_button_x, BUTTON_MENU_Y - BUTTON_MENU_LABEL_HEIGHT))
				.size(vec2(BUTTON_SIZE, BUTTON_MENU_LABEL_HEIGHT))
				.ui(ui);
			widgets::Label::new("Question Marking")
				.position(vec2(question_button_x, BUTTON_MENU_Y - BUTTON_MENU_LABEL_HEIGHT))
				.size(vec2(BUTTON_SIZE, BUTTON_MENU_LABEL_HEIGHT))
				.ui(ui);
			if let Language::English = ui_state.language {
				if widgets::Button::new("English")
					.size(vec2(BUTTON_SIZE, BUTTON_SIZE))
					.position(vec2(language_button_x, BUTTON_MENU_Y))
					.ui(ui)
				{
					event_handler.add(GUIEvent::SwitchLanguage(Language::Japanese));
				}
			} else {
				if widgets::Button::new("Japanese")
					.size(vec2(BUTTON_SIZE, BUTTON_SIZE))
					.position(vec2(language_button_x, BUTTON_MENU_Y))
					.ui(ui)
				{
					event_handler.add(GUIEvent::SwitchLanguage(Language::English));
				}
			}
			if let ModifyMode::Question = self.board_modify_mode {
				if widgets::Button::new("ON")
					.size(vec2(BUTTON_SIZE, BUTTON_SIZE))
					.position(vec2(question_button_x, BUTTON_MENU_Y))
					.ui(ui)
				{
					self.board_modify_mode = ModifyMode::Flag;
					event_handler.add(GUIEvent::SetQuestionMode(ModifyMode::Flag));
				}
			} else {
				if widgets::Button::new("OFF")
					.size(vec2(BUTTON_SIZE, BUTTON_SIZE))
					.position(vec2(question_button_x, BUTTON_MENU_Y))
					.ui(ui)
				{
					self.board_modify_mode = ModifyMode::Question;
					event_handler.add(GUIEvent::SetQuestionMode(ModifyMode::Question));
				}
			}
		});
	}
}

fn render_counter(
	count: &mut usize,
	ui: &mut Ui,
	textures: &TextureStore,
	position: Vec2,
	title: String,
	min: usize,
	max: usize,
) {
	let digits: Vec<usize> = {
		let digits = count.to_string();
		let digits = format!("{:0>3}", digits);
		digits.chars().map(|i| (i.to_digit(10u32).unwrap_or(0)) as usize).collect()
	};

	const COUNTER_DIGIT_WIDTH: f32 = 13f32 * 2.0;
	const COUNTER_DIGIT_HEIGHT: f32 = 23f32 * 2.0;
	const COUNTER_BUTTON_HEIGHT: f32 = 30f32;
	const COUNTER_BUTTON_MARGIN: f32 = 10f32;
	const BUTTON_OFFSET_HEIGHT: f32 = (COUNTER_DIGIT_HEIGHT - COUNTER_BUTTON_HEIGHT) * 0.5;

	let counter_width = digits.len() as f32 * COUNTER_DIGIT_WIDTH;
	let position = position - vec2(counter_width * 0.5, 0.0);
	for (x, digit) in digits.iter().enumerate() {
		let position = vec2(COUNTER_DIGIT_WIDTH * x as f32, 0f32) + position;
		widgets::Texture::new(textures.numbers[*digit])
			.size(COUNTER_DIGIT_WIDTH, COUNTER_DIGIT_HEIGHT)
			.position(position)
			.ui(ui);
	}
	if widgets::Button::new("+")
		.size(vec2(COUNTER_BUTTON_HEIGHT, COUNTER_BUTTON_HEIGHT))
		.position(position + vec2(counter_width + COUNTER_BUTTON_MARGIN, BUTTON_OFFSET_HEIGHT))
		.ui(ui)
	{
		*count += 1;
	}
	if widgets::Button::new("-")
		.size(vec2(COUNTER_BUTTON_HEIGHT, COUNTER_BUTTON_HEIGHT))
		.position(position - vec2(COUNTER_BUTTON_HEIGHT + COUNTER_BUTTON_MARGIN, -BUTTON_OFFSET_HEIGHT))
		.ui(ui)
	{
		if *count > min {
			*count -= 1;
		}
	}
	if widgets::Button::new("++")
		.size(vec2(COUNTER_BUTTON_HEIGHT, COUNTER_BUTTON_HEIGHT))
		.position(
			position
				+ vec2(
					counter_width + COUNTER_BUTTON_MARGIN * 2.0 + COUNTER_BUTTON_HEIGHT,
					BUTTON_OFFSET_HEIGHT,
				),
		)
		.ui(ui)
	{
		*count += 10;
	}
	if widgets::Button::new("--")
		.size(vec2(COUNTER_BUTTON_HEIGHT, COUNTER_BUTTON_HEIGHT))
		.position(position - vec2((COUNTER_BUTTON_HEIGHT + COUNTER_BUTTON_MARGIN) * 2.0, -BUTTON_OFFSET_HEIGHT))
		.ui(ui)
	{
		if *count as isize - 10 > min as isize {
			*count -= 10;
		} else {
			*count = min;
		}
	}
	if *count > max {
		*count = max;
	}
	if *count < min {
		*count = min;
	}
	let label_height = 20f32;
	widgets::Label::new(title)
		.position(position - vec2(0f32, label_height))
		.size(vec2(counter_width, label_height))
		.ui(ui);
}