use std::time::Instant;

use super::OutfitSet;
use galactica_content as content;

#[derive(Debug)]
pub struct Ship {
	// Metadata values
	pub ct_handle: content::ShipHandle,
	pub faction: content::FactionHandle,
	pub outfits: OutfitSet,

	// State values
	// TODO: unified ship stats struct, like space
	pub hull: f32,
	pub shields: f32,

	// Utility values
	/// The last time this ship was damaged
	pub last_hit: Instant,
}

impl Ship {
	pub fn new(
		ct: &content::Content,
		ct_handle: content::ShipHandle,
		faction: content::FactionHandle,
		outfits: OutfitSet,
	) -> Self {
		let s = ct.get_ship(ct_handle);
		let shields = outfits.get_shield_strength();
		Ship {
			ct_handle,
			faction,
			outfits,
			last_hit: Instant::now(),

			// Initial stats
			hull: s.hull,
			shields,
		}
	}

	/// If this ship is dead, it will be removed from the game.
	pub fn is_dead(&self) -> bool {
		self.hull <= 0.0
	}

	/// Hit this ship with the given amount of damage
	pub fn apply_damage(&mut self, mut d: f32) {
		if self.is_dead() {
			return;
		}
		if self.shields >= d {
			self.shields -= d
		} else {
			d -= self.shields;
			self.shields = 0.0;
			self.hull = 0f32.max(self.hull - d);
		}
		self.last_hit = Instant::now();
	}

	/// Update this ship's state by `t` seconds
	pub fn step(&mut self, t: f32) {
		let time_since = self.last_hit.elapsed().as_secs_f32();
		if self.shields != self.outfits.get_shield_strength() {
			for g in self.outfits.iter_shield_generators() {
				if time_since >= g.delay {
					self.shields += g.generation * t;
					if self.shields > self.outfits.get_shield_strength() {
						self.shields = self.outfits.get_shield_strength();
						break;
					}
				}
			}
		}
	}
}