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

use super::{DELTA_TIME, sampler::BrownianNoise, resampler::{Resampler, SmoothstepResampler}};

const TIME: f32 = 0.5;
const FADE_IN: f32 = TIME / 64.0;

const SEED: u64 = 490170471;

trait FlagSoundType {
	fn generate() {
		let mut amplitude_noise = SmoothstepResampler::new(BrownianNoise::new(0.25, SEED));
		let mut frequency_noise = SmoothstepResampler::new(BrownianNoise::new(0.125, SEED + 1));
		let mut phase_noise = SmoothstepResampler::new(BrownianNoise::new(0.1875, SEED + 2));
		let mut extra_noise = SmoothstepResampler::new(BrownianNoise::new(0.375, SEED + 3));

		super::generate(Self::PATH, Self::TIME, Self::AMPLITUDE, |t| {
			let mut wave = 0.0;
			let freq = frequency_noise.next(500.0 * DELTA_TIME) * 48.0 + Self::FREQ;
			let phase = phase_noise.next(300.0 * DELTA_TIME) * 20.0;
			for i in 0..8 {
				let amplitude = (1.0 - t / TIME).powf((1.0 + i as f32 * 0.75) * Self::FADE_OUT_POW_MUL);
				let w = (t * freq * (i as f32 + 1.0) * TAU + phase).sin();
				wave += w / (i + 1) as f32 * amplitude;
			}

			let mut amplitude = {
				let a = amplitude_noise.next(Self::AMPLITUDE_FREQ * DELTA_TIME);
				a.abs().powf(Self::AMPLITUDE_POW) * a.signum()
			};
			amplitude *= 1.0 - (1.0 - (t / FADE_IN).min(1.0)).powi(2); // Fade in

			wave * amplitude * (extra_noise.next(28000.0 * DELTA_TIME) * 0.325 + 0.625)
		});
	}

	const PATH: &'static str;
	const TIME: f32;
	const AMPLITUDE: f32;
	const FREQ: f32;
	const FADE_OUT_POW_MUL: f32;
	const AMPLITUDE_FREQ: f32;
	const AMPLITUDE_POW: f32;
}

struct Capture;

impl FlagSoundType for Capture {
	const PATH: &'static str = "flag_capture";
	const TIME: f32 = 0.5;
	const AMPLITUDE: f32 = 0.46875;
	const FREQ: f32 = 200.0;
	const FADE_OUT_POW_MUL: f32 = 1.0;
	const AMPLITUDE_FREQ: f32 = 600.0;
	const AMPLITUDE_POW: f32 = 0.75;
}

struct Drop;

impl FlagSoundType for Drop {
	const PATH: &'static str = "flag_drop";
	const TIME: f32 = 0.4375;
	const AMPLITUDE: f32 = 0.625;
	const FREQ: f32 = 131.25;
	const FADE_OUT_POW_MUL: f32 = 3.0;
	const AMPLITUDE_FREQ: f32 = 100.0;
	const AMPLITUDE_POW: f32 = 0.5;
}

pub fn generate_capture() {
	Capture::generate();
}

pub fn generate_drop() {
	Drop::generate();
}
