use bevy::{asset::AssetPath, prelude::*};

use crate::{player::Player, score::Score, GameState, START_POSITION};

pub struct HUDPlugin;

impl Plugin for HUDPlugin {
	fn build(&self, app: &mut App) {
		app.add_systems(Startup, setup);
		app.add_systems(Update, start_button_logic);
	}
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
	// let asset_path: AssetPath = "embedded://avoid_rs/assets/Xolonium-Regular.ttf".into();
	let asset_path: AssetPath = "Xolonium-Regular.ttf".into();
	let font: Handle<Font> = asset_server.load(asset_path);

	// let path = Path::new("avoid-rs").join("assets/Xolonium-Regular.ttf");
	// let source = AssetSourceId::from("embedded");
	// let asset_path = AssetPath::from_path(&path).with_source(source);
	// let font: Handle<_> = asset_server.load(asset_path);

	// score UI, top middle
	commands
		.spawn((Node {
			width: Val::Percent(100.0),
			align_items: AlignItems::Center,
			justify_content: JustifyContent::Center,
			..Default::default()
		},))
		.with_child((
			ScoreText,
			Text::new("0"),
			TextFont {
				font: font.clone(),
				font_size: 64.0,
				..Default::default()
			},
			TextLayout::new_with_justify(JustifyText::Center),
		));

	// game info, middle of the screen
	commands
		.spawn((
			IntroMessageText,
			Node {
				width: Val::Percent(100.0),
				height: Val::Percent(100.0),
				align_items: AlignItems::Center,
				justify_content: JustifyContent::Center,
				..Default::default()
			},
		))
		.with_child((
			Text::new("Dodge the creeps!"),
			TextFont {
				font: font.clone(),
				font_size: 64.0,
				..Default::default()
			},
			TextLayout::new_with_justify(JustifyText::Center),
		));

	commands
		.spawn((
			StartMenuUI,
			Node {
				width: Val::Percent(100.0),
				height: Val::Percent(90.0),
				align_items: AlignItems::End,
				justify_content: JustifyContent::Center,
				..Default::default()
			},
		))
		.with_children(|parent| {
			parent
				.spawn((
					StartButton,
					Node {
						width: Val::Px(200.0),
						height: Val::Px(100.0),
						border: UiRect::all(Val::Px(5.0)),
						justify_content: JustifyContent::Center,
						align_items: AlignItems::Center,
						..Default::default()
					},
					BorderColor(Color::BLACK),
					BorderRadius::all(Val::Px(10.0)),
					BackgroundColor::from(Color::srgb(0.15, 0.15, 0.15)),
				))
				.with_child((
					Text::new("Start"),
					TextFont {
						font: font.clone(),
						font_size: 64.0,
						..Default::default()
					},
					TextColor::from(Color::srgb(0.9, 0.9, 0.9)),
				));
		});
}

#[derive(Component, Default)]
#[require(Text)]
pub struct ScoreText;

#[derive(Component)]
#[require(StartMenuUI, Text)]
pub struct IntroMessageText;

#[derive(Component)]
#[require(StartMenuUI, Button)]
pub struct StartButton;

#[derive(Component, Default)]
pub struct StartMenuUI;

fn start_button_logic(
	current_state: Res<State<GameState>>,
	mut state: ResMut<NextState<GameState>>,
	mut score: ResMut<Score>,
	gamepads: Query<&Gamepad>,
	mut button: Query<(&Interaction, &mut BorderColor), With<StartButton>>,
	mut player_query: Query<(&mut Transform, &mut Visibility), With<Player>>,
	mut ui_elems_query: Query<&mut Visibility, (With<StartMenuUI>, Without<Player>)>,
	mut score_text_query: Query<&mut Text, With<ScoreText>>,
) {
	if current_state.get() == &GameState::Playing {
		return;
	};

	let mut score_text = score_text_query.single_mut();
	let (mut player_transform, mut player_visibility) = player_query.single_mut();

	let gamepad = gamepads.get_single();

	if let Ok(gamepad) = gamepad {
		if gamepad.just_pressed(GamepadButton::Start) {
			start_game(
				&mut score_text,
				&mut score,
				&mut state,
				&mut ui_elems_query,
				&mut player_visibility,
				&mut player_transform,
			);
			return;
		}
	}

	let (interaction, mut border_color) = button.single_mut();

	match *interaction {
		Interaction::Pressed => {
			start_game(
				&mut score_text,
				&mut score,
				&mut state,
				&mut ui_elems_query,
				&mut player_visibility,
				&mut player_transform,
			);
		}
		Interaction::Hovered => border_color.0 = Color::WHITE,
		Interaction::None => border_color.0 = Color::BLACK,
	}
}

fn start_game(
	score_text: &mut Text,
	score: &mut Score,
	state: &mut NextState<GameState>,
	ui_elems: &mut Query<&mut Visibility, (With<StartMenuUI>, Without<Player>)>,
	player_visibility: &mut Visibility,
	player_transform: &mut Transform,
) {
	score.0 = 0;
	score_text.0 = format!("{}", score.0);

	state.set(GameState::Playing);

	for mut elem in ui_elems {
		*elem = Visibility::Hidden;
	}

	*player_visibility = Visibility::Visible;
	player_transform.translation = START_POSITION;
}
