use anyhow::Result;
use async_trait::async_trait;
use oxios_gateway::channel::Channel;
use oxios_gateway::message::{IncomingMessage, OutgoingMessage};
use std::sync::Arc;
use tokio::sync::mpsc;
use tokio::sync::Mutex;
use crate::session::Session;
pub struct CliChannel {
incoming_rx: Mutex<mpsc::Receiver<IncomingMessage>>,
incoming_tx: mpsc::Sender<IncomingMessage>,
session: Arc<std::sync::Mutex<Session>>,
}
impl CliChannel {
pub fn new(buffer: usize) -> Self {
let (incoming_tx, incoming_rx) = mpsc::channel(buffer);
let session = Arc::new(std::sync::Mutex::new(Session::new(None)));
Self {
incoming_rx: Mutex::new(incoming_rx),
incoming_tx,
session,
}
}
pub fn sender(&self) -> mpsc::Sender<IncomingMessage> {
self.incoming_tx.clone()
}
pub fn handle(&self) -> CliChannelHandle {
CliChannelHandle {
incoming_tx: self.incoming_tx.clone(),
session: self.session.clone(),
}
}
}
#[async_trait]
impl Channel for CliChannel {
fn name(&self) -> &str {
"cli"
}
async fn receive(&self) -> Result<Option<IncomingMessage>> {
let mut rx = self.incoming_rx.lock().await;
Ok(rx.recv().await)
}
async fn send(&self, msg: OutgoingMessage) -> Result<()> {
println!("{}", msg.content);
Ok(())
}
}
impl std::fmt::Debug for CliChannel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CliChannel").finish()
}
}
#[derive(Debug, Clone)]
pub struct CliChannelHandle {
pub incoming_tx: mpsc::Sender<IncomingMessage>,
session: Arc<std::sync::Mutex<Session>>,
}
impl CliChannelHandle {
pub fn from_channel(channel: &CliChannel) -> Self {
channel.handle()
}
pub async fn send_user_message(&self, content: String) -> Result<()> {
let mut msg = IncomingMessage::new("cli", "cli-user", &content);
{
let session = self.session.lock().unwrap();
msg.metadata
.insert("session_id".to_owned(), session.id.to_string());
}
self.incoming_tx
.send(msg)
.await
.map_err(|e| anyhow::anyhow!("{e}"))?;
Ok(())
}
pub fn touch_session(&self) {
if let Ok(mut session) = self.session.lock() {
session.touch();
}
}
pub fn reset_session(&self) {
if let Ok(mut session) = self.session.lock() {
*session = Session::new(None);
}
}
pub fn session_id(&self) -> uuid::Uuid {
self.session.lock().map(|s| s.id).unwrap_or_default()
}
}