use std::any::TypeId;
use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::Hash;
use crate::clone_any::CloneAny;
use crate::context::FlowContext;
use crate::error::FlowError;
pub trait FlowState: Clone + Copy + Eq + Hash + Debug + Send + Sync + 'static {
fn is_terminal(&self) -> bool;
fn is_initial(&self) -> bool;
fn all_states() -> &'static [Self];
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TransitionType { Auto, External, Branch, SubFlow }
pub enum GuardOutput {
Accepted { data: HashMap<TypeId, Box<dyn CloneAny>> },
Rejected { reason: String },
Expired,
}
pub trait StateProcessor<S: FlowState>: Send + Sync {
fn name(&self) -> &str;
fn requires(&self) -> Vec<TypeId>;
fn produces(&self) -> Vec<TypeId>;
fn process(&self, ctx: &mut FlowContext) -> Result<(), FlowError>;
}
pub trait TransitionGuard<S: FlowState>: Send + Sync {
fn name(&self) -> &str;
fn requires(&self) -> Vec<TypeId>;
fn produces(&self) -> Vec<TypeId>;
fn validate(&self, ctx: &FlowContext) -> GuardOutput;
}
pub trait BranchProcessor<S: FlowState>: Send + Sync {
fn name(&self) -> &str;
fn requires(&self) -> Vec<TypeId>;
fn decide(&self, ctx: &FlowContext) -> String;
}
pub struct Transition<S: FlowState> {
pub from: S,
pub to: S,
pub transition_type: TransitionType,
pub processor: Option<Box<dyn StateProcessor<S>>>,
pub guard: Option<Box<dyn TransitionGuard<S>>>,
pub branch: Option<Box<dyn BranchProcessor<S>>>,
pub branch_targets: HashMap<String, S>,
pub sub_flow: Option<crate::sub_flow::SubFlowConfig<S>>,
pub timeout: Option<std::time::Duration>,
}