use futures::{Future, IntoFuture, Stream};
use futures::future;
use tokio_core::reactor::{Core, Handle};
use client::data::Config;
use client::{IrcClient, IrcClientFuture, PackedIrcClient, Client};
use error;
use proto::Message;
pub struct IrcReactor {
inner: Core,
handlers: Vec<Box<Future<Item = (), Error = error::IrcError>>>,
}
impl IrcReactor {
pub fn new() -> error::Result<IrcReactor> {
Ok(IrcReactor {
inner: Core::new()?,
handlers: Vec::new(),
})
}
pub fn prepare_client<'a>(&mut self, config: &'a Config) -> error::Result<IrcClientFuture<'a>> {
IrcClient::new_future(self.inner_handle(), config)
}
pub fn connect_client(&mut self, future: IrcClientFuture) -> error::Result<IrcClient> {
self.inner.run(future).map(|PackedIrcClient(client, future)| {
self.register_future(future);
client
})
}
pub fn prepare_client_and_connect(&mut self, config: &Config) -> error::Result<IrcClient> {
self.prepare_client(config).and_then(|future| self.connect_client(future))
}
pub fn register_client_with_handler<F, U>(
&mut self, client: IrcClient, handler: F
) where F: Fn(&IrcClient, Message) -> U + 'static,
U: IntoFuture<Item = (), Error = error::IrcError> + 'static {
self.handlers.push(Box::new(client.stream().for_each(move |message| {
handler(&client, message)
})));
}
pub fn register_future<F>(
&mut self, future: F
) where F: IntoFuture<Item = (), Error = error::IrcError> + 'static {
self.handlers.push(Box::new(future.into_future()))
}
pub fn inner_handle(&self) -> Handle {
self.inner.handle()
}
pub fn run(&mut self) -> error::Result<()> {
let mut handlers = Vec::new();
while let Some(handler) = self.handlers.pop() {
handlers.push(handler);
}
self.inner.run(future::join_all(handlers).map(|_| ()))
}
}