use super::calibration::{MAGNIFICATION, PIXEL_SIZE_NM};

#[derive(Debug)]
struct Settings 
{
	magnification: f64,
	pixel_size_nm: f64
}

impl Settings
{
	pub fn new(magnification: f64, pixel_size_nm: f64) -> Self
	{
		Self
		{
			magnification,
			pixel_size_nm
		}
	}

	pub fn calibration() -> Self
	{
		Self::new(MAGNIFICATION, PIXEL_SIZE_NM)
	}

	pub fn magnification(&self) -> f64
	{
		self.magnification
	}

	pub fn pixel_size_nm(&self) -> f64
	{
		self.pixel_size_nm
	}

}

fn scale_factor(reference: &Settings, measured: &Settings) -> f64
{
	let mag_sf = reference.magnification() / measured.magnification();
	let cam_sf = measured.pixel_size_nm() / reference.pixel_size_nm();
	mag_sf * cam_sf
}

fn align_spatial_frequencies(reference: &Settings, measured: &Settings, qs: &[f64]) -> Vec<f64>
{
	let sf = scale_factor(reference, measured);
	qs.iter().map(|x| x * sf).collect()
}

pub fn align_to_calibration(qs: &[f64], magnification: f64, pixel_size_nm: f64) -> Vec<f64>
{
	let reference = Settings::calibration();
	let measured = Settings::new(magnification, pixel_size_nm);
	align_spatial_frequencies(&reference, &measured, qs)
}

#[cfg(test)]
mod tests 
{
	use super::*;

	#[test]
	fn scale_factor_basic() 
	{
		let reference = Settings::calibration();
		let test = Settings::calibration();
		assert_eq!(scale_factor(&reference, &test), 1.0)
	}

	#[test]
	fn scale_factor_adjusts_for_pixel_size() 
	{
		let reference = Settings::calibration();
		let test = Settings::new(8.0, 6.25);
		assert_eq!(scale_factor(&reference, &test), 0.5)
	}

	#[test]
	fn scale_factor_adjusts_for_magnification() 
	{
		let reference = Settings::calibration();
		let test = Settings::new(16.0, 12.5);
		assert_eq!(scale_factor(&reference, &test), 0.5)
	}
}