// 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, Vec4};

use super::super::Particle;

pub struct Teleportation {
	centre: Vec2,
	size: f32,
	red: f32,
	p0: Vec2,
	p1: Vec2,
	t: f32,
	vel: f32,
	time: f32,
	max_time: f32,
}

impl Teleportation {
	pub fn new(pos: Vec2) -> Teleportation {
		let max_time = rand::random::<f32>() * 3.0 + 5.0;
		Teleportation {
			centre: pos,
			size: (rand::random::<f32>() + 1.0) * 0.046875,
			red: rand::random::<f32>() * 0.125 + 0.375,
			p0: Teleportation::new_point(pos),
			p1: Teleportation::new_point(pos),
			t: 0.0,
			vel: rand::random::<f32>() * 0.5 + 1.0,
			time: max_time,
			max_time,
		}
	}

	fn new_point(centre: Vec2) -> Vec2 {
		centre + Vec2::from_angle(rand::random::<f32>() * TAU) * rand::random::<f32>() * 0.75
	}
}

impl Particle for Teleportation {
	fn get_pos(&self) -> Vec2 { self.p0.lerp(self.p1, self.t * self.t * (3.0 - 2.0 * self.t)) }
	fn get_size(&self) -> f32 { self.size * (self.t * (self.t - 1.0) + 1.0) } // Size is smallest when on the middle of transit

	fn get_colour(&self) -> Vec4 {
		let t = self.time / self.max_time;
		Vec4::new(self.red, 0.25, 0.5, 4.0 * t * (1.0 - t))
	}

	fn update(&mut self, dt: f32) -> bool {
		self.t += self.vel * dt;
		if self.t >= 1.0 {
			self.t %= 1.0;
			self.p0 = self.p1;
			self.p1 = Teleportation::new_point(self.centre);
		}

		self.time -= dt;
		self.time >= 0.0
	}
}
