#![warn(rust_2018_idioms)]
#![deny(clippy::wildcard_imports)]
#![forbid(elided_lifetimes_in_paths, unsafe_code)]

mod assets {
	include!(env!("ASSETS_RS"));
}
mod activities;
mod game;
mod game_over;
mod ui;

use std::env::var;

use self::{
	activities::{house::HouseState, overworld::worldgen::Overworld, Activity},
	game::Ghost
};
use comfy::{
	init_game_config, pollster, run_comfy_main_async, DevConfig, EngineContext,
	EngineState, GameConfig, GameLoop, HashMap, IVec2
};

const GAME_NAME: &str = "Powercreep";

/// true if devtools should be enable
fn dev_from_env() -> bool {
	match var("DEV").as_ref().map(|f| f.as_str()) {
		Ok("false") => false,
		Ok("true") => true,
		#[cfg(debug_assertions)]
		_ => true,
		#[cfg(not(debug_assertions))]
		_ => false
	}
}

#[derive(Debug, Default)]
struct State {
	setup_called: bool,
	activity: Activity,
	ghost: Ghost,
	overworld: Overworld,
	houses: HashMap<IVec2, HouseState>,
	score: f32,
	/// show dev tools
	dev: bool
}

impl State {
	fn get_house_pos(&self) -> Option<IVec2> {
		match self.activity {
			Activity::House(pos) => Some(pos),
			_ => None
		}
	}

	fn house(&self) -> Option<&HouseState> {
		self.houses.get(&self.get_house_pos()?)
	}

	fn house_mut(&mut self, ctx: &mut EngineContext<'_>) -> Option<&mut HouseState> {
		Some(
			self.houses
				.entry(self.get_house_pos()?)
				.or_insert_with(|| HouseState::generate_new_house(ctx))
		)
	}
}

impl GameLoop for State {
	fn new(_c: &mut EngineState) -> Self {
		Default::default()
	}

	fn update(&mut self, ctx: &mut EngineContext<'_>) {
		if !self.setup_called {
			self.dev = dev_from_env();
			game::setup(self, ctx);
			game::setup(self, ctx);
			self.setup_called = true;
		}

		game::update(self, ctx);
		game::draw(self, ctx);
		game::update(self, ctx);
		game::draw(self, ctx);
	}
}

fn config(config: GameConfig) -> GameConfig {
	let dev = if dev_from_env() {
		DevConfig {
			show_fps: true,
			..Default::default()
		}
	} else {
		Default::default()
	};
	GameConfig {
		tonemapping_enabled: true,
		dev,
		target_framerate: 165,
		..config
	}
}

async fn run() {
	init_game_config(GAME_NAME.to_string(), env!("CARGO_PKG_VERSION"), config);
	let mut engine = EngineState::new();
	let game = State::new(&mut engine);
	run_comfy_main_async(game, engine).await;
}

fn main() {
	pollster::block_on(run());
}
