use async_trait::async_trait;
use theatre::prelude::*;

struct RingNode {
    next: Option<Addr<RingNode>>,
}

#[async_trait]
impl Actor for RingNode {
    async fn stopping(&mut self, _ctx: &mut Context<Self>) {
        println!("Actor shutting down");
    }
}

struct RingMessage(usize);

impl Message for RingMessage {
    type Return = usize;
}

#[async_trait::async_trait]
impl Handler<RingMessage> for RingNode {
    async fn handle(
        &mut self,
        mut msg: RingMessage,
        _context: &mut Context<Self>,
    ) -> <RingMessage as Message>::Return {
        println!("Got {}", msg.0);
        msg.0 += 1;
        if msg.0 == 3 {
            let mut d = RingNode { next: None }.spawn().await;
            println!("Here");
            return d.send(msg).await.unwrap();
        }

        match self.next.as_mut() {
            Some(addr) => addr.send(msg).await.unwrap(),
            None => msg.0,
        }
    }
}

#[tokio::main]
async fn main() {
    let c = RingNode { next: None }.spawn().await;

    let b = RingNode { next: Some(c) }.spawn().await;

    let addr = RingNode { next: Some(b) }.spawn().await;

    let mut addr2 = Addr::clone(&addr);
    println!("n: {}", addr2.send(RingMessage(0)).await.unwrap());
}
