use std::any::Any;
use std::sync::Arc;
use std::time::Duration;
use tokio::time::sleep;
use crate::actor::actor::Actor;
use crate::actor_system::{ActorSystem, ActorSystemError};
use crate::address::Addr;
use crate::supervision::SupervisionStrategy;
#[derive(Clone, Copy)]
pub(crate) enum ContextFlag {
Run,
Kill,
Restart
}
pub struct ActorContext {
addr: Addr,
pub(crate) flag: ContextFlag,
sys: Option<Arc<ActorSystem>>
}
impl ActorContext {
pub(crate) fn new(addr: Addr) -> Self {
Self {
addr,
flag: ContextFlag::Run,
sys: None
}
}
pub(crate) fn set_actor_sys(&mut self, sys: Arc<ActorSystem>) {
self.sys = Some(sys);
}
pub fn spawn<S: Send + 'static>(&mut self, actor: Actor<S>, name: String) -> Result<(), ActorSystemError> {
match &self.sys {
None => {
Err(ActorSystemError::ActorNotSpawnedYet)
}
Some(sys) => {
sys.spawn(actor, name)
}
}
}
pub fn spawn_with_supervision<S: Send + Clone>(self: &Arc<Self>, actor: Actor<S>, supervision_strategy: Box<dyn SupervisionStrategy<S> + Send>, name: String) -> Result<(), ActorSystemError> {
match &self.sys {
None => {
Err(ActorSystemError::ActorNotSpawnedYet)
}
Some(sys) => {
sys.spawn_with_supervision(actor, supervision_strategy, name)
}
}
}
pub fn query(&self, name: &str) -> Option<Addr> {
match &self.sys {
None => {
None
}
Some(sys) => {
sys.query(name)
}
}
}
pub fn stop(&self) {
match &self.sys {
None => {}
Some(sys) => {
sys.stop();
}
}
}
pub fn get_addr(&self) -> Addr {
self.addr.clone()
}
pub fn kill(&mut self) {
self.flag = ContextFlag::Kill;
}
pub fn restart(&mut self) {
self.flag = ContextFlag::Restart;
}
pub fn run_async(&self, f: Box<dyn Fn() -> () + Send>) {
tokio::spawn(async move {
f();
});
}
pub fn run_delayed(&self, f: Box<dyn Fn() -> () + Send>, delay: Duration) {
tokio::spawn(async move {
sleep(delay).await;
f();
});
}
pub fn broadcast_tell<M: Send + Any + Clone>(&self, msg: M) -> Result<(), ActorSystemError> {
match &self.sys {
None => {
Err(ActorSystemError::ActorNotSpawnedYet)
}
Some(sys) => {
Ok(sys.broadcast_tell(msg))
}
}
}
pub fn broadcast_ask<M: Send + Any + Clone>(&self, msg: M, reply_to: Addr) -> Result<(), ActorSystemError> {
match &self.sys {
None => {
Err(ActorSystemError::ActorNotSpawnedYet)
}
Some(sys) => {
Ok(sys.broadcast_ask(msg, reply_to))
}
}
}
}