use std::fmt::Debug;
use bitflags::_core::fmt::Formatter;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::{from_ron, to_ron};
use crate::state::global_state::GlobalState;
use dyn_clone::DynClone;
use std::ops::{DerefMut, Deref};
use std::fmt;
use crate::state::mapped_state::MappedState;
use crate::state::environment::Environment;
use serde::de::DeserializeOwned;
pub trait State<T, GS>: DynClone where T: Serialize + Clone + Debug, GS: GlobalState {
fn get_value_mut(&mut self, global_state: &mut GS) -> &mut T;
fn get_value(&mut self, global_state: &GS) -> &T;
fn get_latest_value(&self) -> &T;
fn get_latest_value_mut(&mut self) -> &mut T;
fn get_key(&self) -> Option<&String>;
fn update_dependent_states(&mut self, env: &Environment<GS>);
}
pub trait StateExt<T: Serialize + Clone + Debug + DeserializeOwned + 'static, GS: GlobalState>: State<T, GS> + Sized + 'static {
fn mapped<U: Serialize + Clone + Debug + 'static>(self, map: fn(&T) -> U) -> Box<dyn State<U, GS>> {
let latest_value = self.get_latest_value().clone();
Box::new(MappedState::new(Box::new(self), map, map(&latest_value)))
}
}
impl<X: 'static, T: Serialize + Clone + Debug + DeserializeOwned + 'static, GS: GlobalState> StateExt<T, GS> for X where X: State<T, GS> {}
impl<T: Serialize + Clone + Debug, GS: GlobalState> Debug for dyn State<T, GS> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "State with latest value: {:?}", *self.get_latest_value())
}
}
dyn_clone::clone_trait_object!(<T: Serialize + Clone + Debug, GS: GlobalState> State<T, GS>);
impl<T: Serialize + Clone + Debug, GS: GlobalState> State<T, GS> for Box<dyn State<T, GS>> {
fn get_value_mut(&mut self, global_state: &mut GS) -> &mut T {
self.deref_mut().get_value_mut(global_state)
}
fn get_value(&mut self, global_state: &GS) -> &T {
self.deref_mut().get_value(global_state)
}
fn get_latest_value(&self) -> &T {
self.deref().get_latest_value()
}
fn get_latest_value_mut(&mut self) -> &mut T {
self.deref_mut().get_latest_value_mut()
}
fn get_key(&self) -> Option<&String> {
self.deref().get_key()
}
fn update_dependent_states(&mut self, env: &Environment<GS>) {
self.deref_mut().update_dependent_states(env)
}
}
impl<T: Serialize + Clone + Debug, GS: GlobalState> State<T, GS> for CommonState<T, GS> {
fn get_value_mut(&mut self, global_state: &mut GS) -> &mut T {
self.get_value_mut(global_state)
}
fn get_value(&mut self, global_state: &GS) -> &T {
self.get_value(global_state)
}
fn get_latest_value(&self) -> &T {
self.get_latest_value()
}
fn get_latest_value_mut(&mut self) -> &mut T {
self.get_latest_value_mut()
}
fn get_key(&self) -> Option<&String> {
self.get_key()
}
fn update_dependent_states(&mut self, _: &Environment<GS>) {}
}
#[derive(Clone)]
pub enum CommonState<T, GS> where T: Serialize + Clone + Debug, GS: GlobalState {
LocalState { id: String, value: T },
Value { value: T },
GlobalState {
function: fn(state: &GS) -> T,
function_mut: Option<fn(state: &mut GS) -> T>,
latest_value: T
}
}
impl<T: Serialize + Clone + Debug, U: GlobalState> Debug for CommonState<T, U> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
CommonState::LocalState { id, value } => {
f.debug_struct("State::LocalState")
.field("id", id)
.field("value", value)
.finish()
}
CommonState::Value { value } => {
f.debug_struct("State::Value")
.field("value", value)
.finish()
}
CommonState::GlobalState { latest_value, .. } => {
f.debug_struct("State::GlobalState")
.field("latest_value", latest_value)
.finish()
}
}
}
}
impl<T: Serialize + Clone + Debug, U: GlobalState> CommonState<T, U> {
pub fn get_value_mut(&mut self, global_state: &mut U) -> &mut T {
match self {
CommonState::LocalState { value, .. } => {value}
CommonState::Value { value } => {value}
CommonState::GlobalState { latest_value, function_mut, function } => {
if let Some(n) = function_mut {
*latest_value = n(global_state).clone();
} else {
*latest_value = function(global_state).clone();
}
latest_value
}
}
}
pub fn get_value(&mut self, global_state: &U) -> &T {
match self {
CommonState::LocalState { value, .. } => {value}
CommonState::Value { value } => {value}
CommonState::GlobalState { latest_value, function, .. } => {
*latest_value = function(global_state).clone();
latest_value
}
}
}
pub fn get_latest_value(&self) -> &T {
match self {
CommonState::LocalState { value, .. } => {value}
CommonState::Value { value } => {value}
CommonState::GlobalState { latest_value, .. } => {
latest_value
}
}
}
pub fn get_latest_value_mut(&mut self) -> &mut T {
match self {
CommonState::LocalState { value, .. } => {value}
CommonState::Value { value } => {value}
CommonState::GlobalState { latest_value, .. } => {
latest_value
}
}
}
pub fn get_key(&self) -> Option<&String> {
match self {
CommonState::LocalState {id, ..} => Some(id),
_ => None
}
}
}
impl<T: Clone + Debug + Serialize + 'static, S: GlobalState> CommonState<T, S> {
pub fn new(val: &T) -> Self {
CommonState::Value {
value: val.clone()
}
}
pub fn new_local(key: &str, val: &T) -> Self {
CommonState::LocalState {
id: key.to_string(),
value: val.clone(),
}
}
pub fn new_local_with_key(val: &T) -> Self {
CommonState::LocalState {
id: Uuid::new_v4().to_string(),
value: val.clone(),
}
}
}
pub type LocalStateList = Vec<(String, String)>;
pub trait GetState {
fn update_local_state<'a, T: Deserialize<'a> + Serialize + Clone + Debug, U: GlobalState>(&'a self, state: &mut CommonState<T, U>, global_state: &U);
fn replace_state<T: Serialize + Clone + Debug, U: GlobalState>(&mut self, val: CommonState<T, U>);
}
impl GetState for LocalStateList {
fn update_local_state<'a, T: Deserialize<'a> + Serialize + Clone + Debug, U: GlobalState>(&'a self, state: &mut CommonState<T, U>, global_state: &U) {
match state {
CommonState::LocalState { id, value } => {
let key = &*id;
match self.iter().find(|(try_key, _state)| key.eq(try_key)) {
None => (),
Some((_, val)) => {
*value = from_ron(&val).unwrap();
}
}
}
CommonState::Value { .. } => {}
CommonState::GlobalState {function, latest_value, ..} => {
*latest_value = function(global_state).clone()
}
}
}
fn replace_state<T: Serialize + Clone + Debug, U: GlobalState>(&mut self, val: CommonState<T,U>) {
match val {
CommonState::LocalState { id, value } => {
let val = to_ron(&value).unwrap();
self.retain(|(i, _s)| {
id.ne(i)
});
self.push((id, val));
}
CommonState::Value { .. } => {}
_ => {}
}
}
}
impl<T: GlobalState> Into<CommonState<Uuid, T>> for Uuid {
fn into(self) -> CommonState<Uuid, T> {
CommonState::new(&self)
}
}
impl<T: GlobalState> Into<CommonState<Vec<Uuid>, T>> for Vec<Uuid> {
fn into(self) -> CommonState<Vec<Uuid>, T> {
CommonState::new(&self)
}
}
impl<T: GlobalState> Into<CommonState<u32,T>> for u32 {
fn into(self) -> CommonState<u32,T> {
CommonState::new(&self)
}
}
impl<T: GlobalState> Into<CommonState<f64,T>> for f64 {
fn into(self) -> CommonState<f64,T> {
CommonState::new(&self)
}
}
impl<T: GlobalState> Into<CommonState<String, T>> for String {
fn into(self) -> CommonState<String, T> {
CommonState::new(&self)
}
}
impl<T: GlobalState> Into<CommonState<String, T>> for &str {
fn into(self) -> CommonState<String, T> {
CommonState::new(&self.to_string())
}
}
impl<T: GlobalState> Into<CommonState<bool, T>> for bool {
fn into(self) -> CommonState<bool, T> {
CommonState::new(&self)
}
}
impl<T: GlobalState> Into<Box<dyn State<Uuid, T>>> for Uuid {
fn into(self) -> Box<dyn State<Uuid, T>> {
Box::new(CommonState::new(&self))
}
}
impl<T: GlobalState> Into<Box<dyn State<Vec<Uuid>, T>>> for Vec<Uuid> {
fn into(self) -> Box<dyn State<Vec<Uuid>, T>> {
Box::new(CommonState::new(&self))
}
}
impl<T: GlobalState> Into<Box<dyn State<u32, T>>> for u32 {
fn into(self) -> Box<dyn State<u32, T>> {
Box::new(CommonState::new(&self))
}
}
impl<T: GlobalState> Into<Box<dyn State<f64, T>>> for f64 {
fn into(self) -> Box<dyn State<f64, T>> {
Box::new(CommonState::new(&self))
}
}
impl<T: GlobalState> Into<Box<dyn State<String, T>>> for String {
fn into(self) -> Box<dyn State<String, T>> {
Box::new(CommonState::new(&self))
}
}
impl<T: GlobalState> Into<Box<dyn State<String, T>>> for &str {
fn into(self) -> Box<dyn State<String, T>> {
Box::new(CommonState::new(&self.to_string()))
}
}
impl<T: GlobalState> Into<Box<dyn State<bool, T>>> for bool {
fn into(self) -> Box<dyn State<bool, T>> {
Box::new(CommonState::new(&self))
}
}
impl<T: Serialize + Clone + Debug + 'static, GS: GlobalState> Into<Box<dyn State<T, GS>>> for CommonState<T, GS> {
fn into(self) -> Box<dyn State<T, GS>> {
Box::new(self)
}
}