use bevy_reflect::Reflect;
use serde::{Deserialize, Serialize};
use std::{
fmt::Debug,
hash::Hash,
ops::{BitAnd, BitOr},
};
#[allow(unused)]
use crate::{Shareable, Stat};
pub trait QualifierFlag: BitOr<Self, Output = Self> + Ord + Hash + Shareable {
fn contains(&self, other: &Self) -> bool;
fn intersects(&self, other: &Self) -> bool;
fn is_none_or_intersects(&self, other: &Self) -> bool {
self.is_none() || self.intersects(other)
}
fn set_equals(&self, other: &Self) -> bool;
fn none() -> Self;
fn is_none(&self) -> bool;
}
impl<T> QualifierFlag for T
where
T: BitOr<Self, Output = Self>
+ Ord
+ Hash
+ BitAnd<Self, Output = Self>
+ Default
+ Shareable
+ Copy,
{
fn contains(&self, other: &Self) -> bool {
(*self & *other) == *other
}
fn set_equals(&self, other: &Self) -> bool {
self == other
}
fn intersects(&self, other: &Self) -> bool {
!(*self & *other).is_none()
}
fn none() -> Self {
Self::default()
}
fn is_none(&self) -> bool {
self == &Self::default()
}
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Reflect, Serialize, Deserialize,
)]
pub struct Qualifier<Q: QualifierFlag> {
pub all_of: Q,
pub any_of: Q,
}
impl<Q: QualifierFlag> Default for Qualifier<Q> {
fn default() -> Self {
Self {
any_of: Q::none(),
all_of: Q::none(),
}
}
}
impl<Q: QualifierFlag> From<Q> for Qualifier<Q> {
fn from(value: Q) -> Self {
Qualifier {
all_of: value,
any_of: Q::none(),
}
}
}
impl<Q: QualifierFlag> Qualifier<Q> {
pub fn none() -> Self {
Self {
any_of: Q::none(),
all_of: Q::none(),
}
}
pub fn is_none(&self) -> bool {
self.any_of.is_none() && self.all_of.is_none()
}
pub fn any_of(qualifier: Q) -> Self {
Self {
any_of: qualifier,
all_of: Q::none(),
}
}
pub fn all_of(qualifier: Q) -> Self {
Self {
any_of: Q::none(),
all_of: qualifier,
}
}
pub fn and_any_of(self, qualifier: Q) -> Self {
Self {
any_of: self.any_of | qualifier,
all_of: self.all_of,
}
}
pub fn and_all_of(self, qualifier: Q) -> Self {
Self {
any_of: self.any_of,
all_of: self.all_of | qualifier,
}
}
pub fn qualifies_as(&self, queried: &QualifierQuery<Q>) -> bool {
match queried {
QualifierQuery::Aggregate(some_of) => {
some_of.contains(&self.all_of) && self.any_of.is_none_or_intersects(some_of)
}
QualifierQuery::Exact { any_of, all_of } => {
self.any_of.contains(any_of) && &self.all_of == all_of
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Reflect)]
pub enum QualifierQuery<Q: QualifierFlag> {
Aggregate(Q),
Exact {
any_of: Q,
all_of: Q,
},
}
impl<Q: QualifierFlag> QualifierQuery<Q> {
pub fn qualifies_none(&self) -> bool {
Qualifier::none().qualifies_as(self)
}
pub fn qualify(&self, qualifier: &Qualifier<Q>) -> bool {
qualifier.qualifies_as(self)
}
}
impl<Q: QualifierFlag> Default for QualifierQuery<Q> {
fn default() -> Self {
Self::Aggregate(Q::none())
}
}
impl<Q: QualifierFlag> QualifierQuery<Q> {
pub fn none() -> Self {
Self::Aggregate(Q::none())
}
}
impl<Q: QualifierFlag> From<Q> for QualifierQuery<Q> {
fn from(value: Q) -> Self {
QualifierQuery::Aggregate(value)
}
}