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

use serde::Deserialize;

#[derive(Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Comparison<T>(Op, T);

#[derive(Clone, PartialEq, Eq, Deserialize)]
#[serde(deny_unknown_fields)]
pub enum Op {
	Less,
	LessEqual,
	Equal,
	NotEqual,
	GreaterEqual,
	Greater,
}

impl<T> Comparison<T> where T: PartialOrd {
	pub fn test(&self, lhs: T) -> bool {
		let Some(cmp) = lhs.partial_cmp(&self.1) else {
			// Can happen if there's a NaN, in which op(NaN, x) returns false unless op is `!=`
			return self.0 == Op::NotEqual;
		};

		match self.0 {
			Op::Less => cmp == Ordering::Less,
			Op::LessEqual => cmp != Ordering::Greater,
			Op::Equal => cmp == Ordering::Equal,
			Op::NotEqual => cmp != Ordering::Equal,
			Op::GreaterEqual => cmp != Ordering::Less,
			Op::Greater => cmp == Ordering::Greater,
		}
	}
}
