use crate::router::{Address, Cacheable, Kind, Message, Payload};
use color_eyre::eyre::{eyre, Result};
use ratatui::{
prelude::*,
widgets::{Block, BorderType, Borders, Paragraph},
};
use std::collections::HashMap;
use tokio::sync::mpsc;
#[derive(Debug)]
pub struct StateDisplay {
message_tx_to_router: mpsc::UnboundedSender<Message>,
message_rx_from_router: Option<mpsc::UnboundedReceiver<Message>>,
pub message_tx_to_self: mpsc::UnboundedSender<Message>,
cache: HashMap<String, String>,
}
impl StateDisplay {
pub fn new(tx: mpsc::UnboundedSender<Message>) -> StateDisplay {
let (message_tx_to_self, message_rx_from_router) =
mpsc::unbounded_channel::<Message>();
StateDisplay {
message_tx_to_router: tx,
message_rx_from_router: Some(message_rx_from_router),
message_tx_to_self,
cache: HashMap::new(),
}
}
pub fn ask_for_key_sync(
&mut self,
handle: tokio::runtime::Handle,
) -> Result<String> {
let request = Message {
source: Address::StateDisplay,
destination: Address::IrxClient,
payload: Payload::Empty,
tag: None,
cacheable: Cacheable::No,
kind: Kind::Ask,
};
self.message_tx_to_router.send(request)?;
let mut response_receiver = self
.message_rx_from_router
.take()
.ok_or_else(|| eyre!("failed to take ownership of receiver"))?;
let (api_key, receiver) = futures::executor::block_on(async {
handle
.spawn(async {
match response_receiver.recv().await {
Some(message) => match message.payload {
Payload::ApiKey(key) => Ok((key.to_string(), response_receiver)),
_ => Err(eyre!("invalid payload")),
},
None => Err(eyre!("no message received")),
}
})
.await?
})?;
self.message_rx_from_router = Some(receiver);
Ok(api_key)
}
pub fn get_tx_handle(&self) -> mpsc::UnboundedSender<Message> {
self.message_tx_to_self.clone()
}
fn state_display(&mut self) -> Result<Paragraph<'_>> {
let api_key = if let Some(key) = self.cache.get("api_key") {
key.clone()
} else {
let key = self.ask_for_key_sync(tokio::runtime::Handle::current())?;
self.cache.insert(String::from("api_key"), key.clone());
key
};
let time = chrono::Utc::now();
let text = vec![
Line::from(format!("{time}")),
Line::from(""),
Line::from("IRX Client:"),
Line::from(format!(" API key: {api_key}")),
Line::from(" Found: ?".to_string()),
Line::from(" Path: ?".to_string()),
Line::from(" Value: ?".to_string()),
Line::from(" Tier: ?".to_string()),
Line::from(" Requests:"),
Line::from(" This session: ?".to_string()),
Line::from(" Lifetime: ?".to_string()),
];
Ok(
Paragraph::new(text)
.block(
Block::default()
.title("State")
.title_alignment(Alignment::Center)
.borders(Borders::ALL)
.border_style(Style::default())
.border_type(BorderType::Rounded),
)
.alignment(Alignment::Left),
)
}
fn layer(area: Rect) -> Rect {
area
}
pub fn render(&mut self, area: Rect, f: &mut Frame<'_>) -> Result<()> {
let layer = Self::layer(area);
let text = self.state_display()?;
f.render_widget(text, layer);
Ok(())
}
}