use futures::Future;
use nostr_rs_client::{Error as ClientError, Event, Pool};
use nostr_rs_types::{client::Subscribe, Request, Response};
use std::pin::Pin;
use tokio::sync::mpsc;

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("Nostr: {0}")]
    Addr(#[from] nostr_rs_types::types::addr::Error),

    #[error("client: {0}")]
    Client(#[from] ClientError),
}

fn on_connection(
    host: &str,
    _socket: mpsc::Sender<Request>,
) -> Pin<Box<dyn Future<Output = ()> + Send>> {
    println!("Reconnecting to {}", host);
    Box::pin(async move {
        let _ = _socket.send(Subscribe::default().into()).await;
    })
}

#[tokio::main]
async fn main() {
    env_logger::init();
    let mut clients = Pool::new()
        .connect_to("wss://relay.damus.io/", Some(on_connection))
        .expect("valid url")
        .connect_to("wss://brb.io", Some(on_connection))
        .expect("valid url")
        .connect_to("wss://nos.lol", Some(on_connection))
        .expect("valid url")
        .connect_to("wss://relay.current.fyi", Some(on_connection))
        .expect("valid url")
        .connect_to("wss://eden.nostr.land", Some(on_connection))
        .expect("valid url")
        .connect_to("wss://relay.snort.social", Some(on_connection))
        .expect("valid url");

    clients.send(Subscribe::default().into()).await;

    loop {
        if let Some((msg, relayed_by)) = clients.recv().await {
            match msg {
                Event::Response(r) => match *r {
                    Response::Event(x) => {
                        println!("{} => {:?}", relayed_by, x);
                    }
                    Response::EndOfStoredEvents(_) => {}
                    msg => {
                        println!("{} {:?}", relayed_by, msg);
                    }
                },
                msg => {
                    println!("{} {:?}", relayed_by, msg);
                }
            }
        }
    }
}
