use super::{Aim, Model};
use crate::reply::queue::QueueRow;
use crate::ui::Channel;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Asking {
pub channel: Channel,
pub rows: Vec<QueueRow>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Section {
pub header: String,
pub rows: Vec<(Channel, QueueRow)>,
}
impl Model {
pub(super) fn seen_name(
&self,
channel: &Channel,
acked: &crate::reply::queue::Acknowledged,
) -> String {
let aimed = self
.aim
.as_ref()
.is_some_and(|aim| aim.address == acked.workspace);
self.waiting
.iter()
.filter(|held| held.channel.name == channel.name)
.flat_map(|held| held.rows.iter())
.chain(&acked.rows)
.find(|row| row.workspace == acked.workspace && row.agent == acked.agent)
.map(|row| row.display.clone())
.or_else(|| {
self.rows()
.into_iter()
.find(|row| aimed && row.root_id == acked.agent)
.map(|row| row.display)
})
.unwrap_or_else(|| format!("{}/{}", acked.workspace, acked.agent))
}
pub fn begin_queue(&mut self) {
self.stand(super::Listing::Queue);
}
pub fn close_queue(&mut self) {
self.put_down(super::Listing::Queue);
}
pub(super) fn asking(&mut self, channel: &Channel, rows: Vec<QueueRow>) {
let answered = Asking {
channel: channel.clone(),
rows,
};
match self
.waiting
.iter_mut()
.find(|held| held.channel.name == channel.name)
{
Some(held) => *held = answered,
None => self.waiting.push(answered),
}
}
pub fn sections(&self) -> Vec<Section> {
let engines = self.folded();
let mut out: Vec<(String, Section)> = Vec::new();
for asked in &self.waiting {
let key = self.engine_of(&asked.channel.name);
let at = out
.iter()
.position(|(held, _)| *held == key)
.unwrap_or_else(|| {
let header = engines
.iter()
.find(|engine| engine.holds(&asked.channel.name))
.map_or_else(
|| crate::ui::roster::header(&asked.channel),
super::Engine::header,
);
out.push((
key,
Section {
header,
rows: Vec::new(),
},
));
out.len() - 1
});
if let Some((_, section)) = out.get_mut(at) {
self.keep(&mut section.rows, asked);
}
}
out.into_iter().map(|(_, section)| section).collect()
}
fn keep(&self, rows: &mut Vec<(Channel, QueueRow)>, asked: &Asking) {
for row in &asked.rows {
let seat = (asked.channel.clone(), row.clone());
match rows
.iter_mut()
.find(|(_, held)| held.workspace == row.workspace && held.agent == row.agent)
{
None => rows.push(seat),
Some(kept) if self.wall(&kept.0, &row.workspace).is_none() => *kept = seat,
Some(_) => {}
}
}
}
pub fn wall(&self, channel: &Channel, workspace: &str) -> Option<Aim> {
let chunk = self
.roster
.iter()
.find(|chunk| chunk.channel.name == channel.name)?;
chunk
.walls
.iter()
.find(|wall| wall.workspace == workspace)
.and_then(|wall| chunk.channel.address(wall))
.map(|address| Aim {
channel: chunk.channel.name.clone(),
address,
})
}
pub fn post_seen(&mut self, channel: &Channel, row: &QueueRow) {
if let Some(aim) = self.wall(channel, &row.workspace) {
self.outbox.push(super::Posted::act(crate::verbs::seen(
aim.address,
row.agent.clone(),
)));
}
}
pub fn post_answer(&mut self, channel: &Channel, row: &QueueRow, verdict: &str, scope: &str) {
if let Some(aim) = self.wall(channel, &row.workspace) {
self.outbox.push(super::Posted::act(crate::verbs::answer(
aim.address,
row.agent.clone(),
verdict.to_owned(),
Some(scope.to_owned()),
)));
}
}
pub fn go_to(&mut self, channel: &Channel, row: &QueueRow) {
let Some(aim) = self.wall(channel, &row.workspace) else {
return;
};
self.aim_at(&aim.channel, &aim.address);
self.select(&row.agent.clone());
self.close_queue();
}
}
#[cfg(test)]
mod tests;