use std::collections::HashMap;
use std::sync::RwLock;
pub struct Message {
    pub kind: String,
    pub json: String,
}
pub type Implementation = fn(&Message) -> ();
struct MessageHandler {
    implementation: Implementation,
}
impl MessageHandler {
    pub fn new(implementation: Implementation) -> Self {
        Self { implementation }
    }
    pub fn handle(&self, msg: &Message) {
        let _ = &(self.implementation)(msg);
    }
}
pub struct Mediator {
    storage: RwLock<HashMap<String, Vec<Implementation>>>,
}
impl Mediator {
    pub fn new() -> Self {
        let data = HashMap::with_capacity(100);
        let storage = RwLock::new(data);
        Self { storage }
    }
    pub fn add(&mut self, kind: String, handler: Implementation) {
        let key = kind.clone();
        let mut backing = self.storage.write().unwrap();
        let target = &mut *backing;
        if target.contains_key(&key) {
            let handlers = target.get_mut(&key).unwrap();
            handlers.push(handler);
        } else {
            let mut handlers: Vec<Implementation> = Vec::new();
            handlers.push(handler);
            target.insert(key, handlers);
        }
    }
    pub fn invoke(&self, msg: &Message) {
        let backing = self.storage.read().unwrap();
        let target = &*backing;
        if !target.contains_key(&msg.kind) {
            return;
        }
        let handlers = target.get(&msg.kind).unwrap();
        for handler in handlers {
            let wrapper = MessageHandler::new(*handler);
            wrapper.handle(msg);
        }
    }
}
use std::collections::HashMap;
use std::sync::RwLock;
pub struct Message {
    pub kind: String,
    pub json: String,
}
pub type Implementation = fn(&Message) -> ();
struct MessageHandler {
    implementation: Implementation,
    message: Message,
}
impl MessageHandler {
    pub fn new(implementation: Implementation, message: Message) -> Self {
        Self {
            implementation,
            message,
        }
    }
    pub fn handle(&self) {
        let _ = &(self.implementation)(&self.message);
    }
}
pub struct Mediator {
    storage: RwLock<HashMap<String, Vec<Implementation>>>,
}
impl Mediator {
    pub fn new() -> Self {
        let data = HashMap::with_capacity(100);
        let storage = RwLock::new(data);
        Self { storage }
    }
    pub fn add(&mut self, kind: String, handler: Implementation) {
        let key = kind.clone();
        let mut backing = self.storage.write().unwrap();
        let target = &mut *backing;
        if target.contains_key(&key) {
            let handlers = target.get_mut(&key).unwrap();
            handlers.push(handler);
        } else {
            let mut handlers: Vec<Implementation> = Vec::new();
            handlers.push(handler);
            target.insert(key, handlers);
        }
    }
    pub fn invoke(&self, msg: &Message) {
        let kind = msg.kind.clone();
        let json = msg.json.clone();
        let backing = self.storage.read().unwrap();
        let target = &*backing;
        if !target.contains_key(&msg.kind) {
            return;
        }
        let handlers = target.get(&msg.kind).unwrap();
        for handler in handlers {
            let c_kind = kind.clone();
            let c_json = json.clone();
            let c_handler = (*handler).clone();
            tokio::spawn(async move {
                let wrapper = MessageHandler::new(
                    c_handler,
                    Message {
                        kind: c_kind,
                        json: c_json,
                    },
                );
                wrapper.handle();
            });
        }
    }
}