// Copyright Marcus Del Favero 2025
// Licensed under the GNU AGPLv3 with an exception, see `README.md` for details
use std::f32::consts::TAU;

use glam::Vec2;

use crate::utils::maths;

#[derive(Clone)]
pub struct LocalForcefield {
	time: f32,
	time_left: f32,
	rotation: Vec2,
	gradient_pulse: f32,
	lightning_pulse: f32,
}

const FADE_IN_TIME: f32 = 0.5;
const FADE_OUT_TIME: f32 = 2.0;

impl LocalForcefield {
	pub fn new() -> LocalForcefield {
		LocalForcefield {
			time: 0.0,
			time_left: 0.0,
			rotation: Vec2::from_angle(rand::random::<f32>() * TAU),
			gradient_pulse: rand::random::<f32>() * TAU,
			lightning_pulse: rand::random::<f32>() * TAU,
		}
	}

	pub fn new_existing() -> LocalForcefield {
		LocalForcefield {
			time: f32::INFINITY,
			time_left: f32::INFINITY, // Incorrect but will be fixed on the next call to `update`
			.. LocalForcefield::new()
		}
	}

	pub fn get_fade(&self) -> f32 {
		maths::smoothstep((self.time / FADE_IN_TIME).min(self.time_left / FADE_OUT_TIME).clamp(0.0, 1.0))
	}

	pub fn get_rotation(&self) -> [f32; 2] { self.rotation.to_array() }
	pub fn get_gradient_pulse(&self) -> f32 { self.gradient_pulse }
	pub fn get_lightning_pulse(&self) -> f32 { self.lightning_pulse }

	pub fn shift(self, time_shift: f32) -> LocalForcefield {
		/*
		 * Subtracting for the time left as this time decreases over time rather
		 * than increases (it's the remaining time of the effect).
		 */
		LocalForcefield {
			time: self.time + time_shift,
			time_left: self.time_left - time_shift,
			.. self
		}
	}

	pub fn update(&mut self, time_left: f32, dt: f32) {
		/*
		 * Prevents a sudden change in the fade when a forcefield is fading out
		 * but the player renews the effect (collecting a powerup or colliding
		 * with a special area).
		 */
		if time_left > self.time_left {
			self.time = self.time.min(self.time_left / FADE_OUT_TIME * FADE_IN_TIME);
		}

		self.time_left = time_left;
		self.time += dt;

		self.gradient_pulse = maths::add_angle(self.gradient_pulse, dt * 12.0);
		self.lightning_pulse = maths::add_angle(self.lightning_pulse, dt * 3.0);
	}
}
