use std::{
collections::HashMap,
sync::{Mutex, OnceLock},
};
use tokio::sync::oneshot;
use crate::{
bindings::Discriminator,
client::Client,
features::scroll::{ScrollRequest, SCROLL_REQ},
};
use super::{Entry, ScrollPosition, ScrollRequestVariant, ScrollResponseVariant, SCROLL_CONFIRMS};
static ID: OnceLock<Mutex<u32>> = OnceLock::new();
pub struct ScrollComponent {
discrim: Discriminator,
client: Client,
}
impl ScrollComponent {
pub fn new(discrim: Discriminator, client: Client) -> Self {
Self { discrim, client }
}
fn get_id(&self) -> u32 {
let mut id = ID.get_or_init(|| Mutex::new(0)).lock().unwrap();
*id += 1;
*id
}
async fn send(&self, content: ScrollRequestVariant) -> Option<ScrollResponseVariant> {
let (sender, reciever) = oneshot::channel();
let id = self.get_id();
if self
.client
.message(
self.discrim.clone(),
serde_json::to_value(ScrollRequest::new(id, content)).unwrap(),
SCROLL_REQ.to_string(),
)
.await
.is_undelivered()
{
return None;
}
SCROLL_CONFIRMS
.get_or_init(|| std::sync::Mutex::new(HashMap::new()))
.lock()
.unwrap()
.insert(id, sender);
reciever.await.ok()
}
}
impl ScrollComponent {
pub async fn add(
&self,
position: ScrollPosition,
entry: Entry,
) -> Option<ScrollResponseVariant> {
self.send(ScrollRequestVariant::AddEntry { position, entry })
.await
}
pub async fn push(&self, entry: Entry) -> Option<ScrollResponseVariant> {
self.add(ScrollPosition::relative(0), entry).await
}
pub async fn update(&self, uid: u32, new: Entry) -> Option<ScrollResponseVariant> {
self.send(ScrollRequestVariant::UpdateEntry { uid, new })
.await
}
pub async fn remove(&self, uid: u32) -> Option<ScrollResponseVariant> {
self.send(ScrollRequestVariant::RemoveEntry { uid }).await
}
}