use crate::route::{DynEndpoint, Endpoint};
use crate::{Connection, StratumRequest};
use async_std::sync::Arc;
use std::collections::HashMap;

pub struct Router<State, CState> {
    routes: HashMap<String, Box<DynEndpoint<State, CState>>>,
}

impl<State: Clone + Send + Sync + 'static, CState: Clone + Send + Sync + 'static>
    Router<State, CState>
{
    pub fn new() -> Router<State, CState> {
        Router {
            routes: HashMap::new(),
        }
    }

    pub fn add(&mut self, method: &str, ep: impl Endpoint<State, CState>) {
        self.routes.insert(method.to_owned(), Box::new(ep));
    }

    pub async fn call(
        &self,
        method: &str,
        values: serde_json::map::Map<String, serde_json::Value>,
        state: State,
        connection: Arc<Connection<CState>>,
    ) {
        let endpoint = match self.routes.get(method) {
            Some(endpoint) => endpoint,
            None => return,
        };

        let request = StratumRequest { state, values };

        endpoint.call(request, connection).await;
    }
}
