mod furniture;
mod grid;
mod player;
mod room;

use crate::assets::ASSETS;
use comfy::{
	delta, main_camera_mut, play_sound_id, random_i32, stop_sound_id, vec2,
	EngineContext, RandomRange as _
};
use grid::Grid;
use indexmap::IndexSet;
use log::error;
use player::Player;
use room::Room;

use super::Activity;

const MAX_ROOMS: i32 = 6;

#[derive(Debug)]
pub struct HouseState {
	current_room_id: usize,
	room_count: usize,
	human_count: usize,
	rooms: Vec<Room>,
	human_rooms: Vec<usize>,
	//grid: Grid,
	player: Player,
	human_layer: bool, //Human, magnetic, electric
	exit_time: f32,

	/// The energy level remaining in the house. Should decrease by itself, and much
	/// faster when inhabited by the ghost.
	pub charge: f32,
	pub max_charge: f32,

	pub sound_playing: bool
}

impl HouseState {
	pub fn generate_new_house(ctx: &mut EngineContext<'_>) -> Self {
		let room_count = random_i32(2, MAX_ROOMS) as usize;
		let human_count = random_i32(1, room_count as i32) as usize;

		let mut possible_rooms: IndexSet<usize> = (0 .. room_count).collect();
		let mut human_rooms = Vec::new();
		for _ in 0 .. human_count {
			if !possible_rooms.is_empty() {
				let random_idx = usize::gen_range(0, possible_rooms.len());

				human_rooms.push(possible_rooms.swap_remove_index(random_idx).unwrap());
			}
		}

		let mut rooms = Vec::new();
		for i in 0 .. room_count {
			rooms.push(Room::new(ctx, human_rooms.contains(&i)));
		}

		let player = Player::new(rooms.first().unwrap());
		let max_charge = f32::gen_range(2_000.0, 5_000.0);
		HouseState {
			current_room_id: 0,
			room_count,
			human_count,
			rooms,
			human_rooms,
			player,
			human_layer: false,
			exit_time: 0.0,
			// TODO this should be lower depending on the time elapsed
			charge: max_charge,
			max_charge,

			sound_playing: false
		}
	}
}

pub fn draw(state: &crate::State, _ctx: &EngineContext<'_>) {
	let Some(house) = state.house() else {
		error!("How can I render a house when I'm not in one?!?");
		return;
	};

	//Draw House
	house
		.rooms
		.get(house.current_room_id)
		.unwrap()
		.draw(house.human_layer, house.player.can_see_metal(0.1));

	//Draw Grid
	//state.house.grid.draw();

	//Draw Player
	house.player.draw();
}

pub fn update(state: &mut crate::State, ctx: &mut EngineContext<'_>) {
	if state.overworld.sound_playing {
		stop_sound_id(ASSETS.music.galactic_rap_speedup);
		state.overworld.sound_playing = false;
	}

	let mut camera = main_camera_mut();
	camera.center = vec2(0.0, 0.0);
	drop(camera);

	let Some(house) = state.house_mut(ctx) else {
		error!("WTF I cannot update a house without a house");
		return;
	};
	let current_room = house.rooms.get(house.current_room_id).unwrap();
	house.player.update(&current_room);

	if !house.sound_playing {
		play_sound_id(ASSETS.music.mesmerizing_galaxy_loop);
		house.sound_playing = true;
	}

	if house.player.is_moving_to_right_room(current_room) {
		if house.current_room_id < (house.room_count - 1) {
			house.current_room_id += 1;

			let current_room = house.rooms.get(house.current_room_id).unwrap();
			house.player.reset_on_room(current_room, true);
		} else {
			house.player.reset_on_room(current_room, false);
		}
	} else if house.player.is_moving_to_left_room(current_room) {
		if house.current_room_id > 0 {
			house.current_room_id -= 1;

			let current_room = house.rooms.get(house.current_room_id).unwrap();
			house.player.reset_on_room(current_room, false);
		} else {
			house.player.reset_on_room(current_room, true);
		}
	}

	if house.player.successfull_attack {
		house.human_layer = true;
	}

	if house.human_layer {
		house.exit_time += delta();
	}

	if house.exit_time >= 2.0 {
		state.score += 500.0;
		state.ghost.overworld_pos -= vec2(0.0, 1.0);
		state.activity = Activity::Overworld;
	}
}
