use ratatui::layout::{Constraint, Layout, Rect};
use ratatui::text::Line;
use ratatui::widgets::{Paragraph, Row, Table, Wrap};
use ratatui::Frame;
use super::Theme;
use crate::tui::app::devices::age_label;
use crate::tui::app::App;
const NETWORK: u16 = 7;
const HEARD: u16 = 9;
const FLAG: u16 = 9;
const ROUTER_MIN: u16 = 21;
pub(super) fn subtitle(app: &App) -> String {
let state = &app.network;
let routers = match state.routers.router_count() {
1 => "1 router".to_string(),
n => format!("{n} routers"),
};
let local = match state.local_number {
Some((network, true)) => format!(" | local network {network} (configured)"),
Some((network, false)) => format!(" | local network {network} (learned)"),
None => String::new(),
};
let asked = match state.routers_asked {
Some(at) => format!("asked {} ago", age_label(app.now, at)),
None => "r asks the routers".to_string(),
};
format!("| {routers}{local} | {asked} ")
}
pub(super) fn draw(frame: &mut Frame, area: Rect, app: &App, theme: &Theme) {
let map = &app.network.routers;
if map.is_empty() {
let text = "No router heard yet. r asks every router for the networks it reaches.";
frame.render_widget(Paragraph::new(Line::styled(text, theme.dim())), area);
return;
}
let rows = map.rows();
let routers: Vec<String> = rows.iter().map(|row| row.routers.join(", ")).collect();
let longest = routers
.iter()
.map(|r| r.chars().count())
.max()
.unwrap_or(0)
.max("Router".len());
let fixed = NETWORK + HEARD + FLAG + 3;
let router_width = u16::try_from(longest)
.unwrap_or(u16::MAX)
.min(area.width.saturating_sub(fixed).max(ROUTER_MIN));
let rows: Vec<Row> = rows
.into_iter()
.zip(routers)
.map(|(row, routers)| {
let flag = if row.duplicate() { "DUPLICATE" } else { "" };
let line = Row::new([
row.network.to_string(),
routers,
age_label(app.now, row.heard),
flag.to_string(),
]);
if row.duplicate() {
line.style(theme.danger())
} else {
line
}
})
.collect();
let widths = [
Constraint::Length(NETWORK),
Constraint::Length(router_width),
Constraint::Length(HEARD),
Constraint::Length(FLAG),
];
let text = "DUPLICATE: several routers claim one network number: a shared \
number, a loop, or a moved route (r asks again).";
let note_height = if map.duplicates().is_empty() {
0
} else if text.len() <= usize::from(area.width) {
1
} else {
2
};
let [table, note] =
Layout::vertical([Constraint::Min(2), Constraint::Length(note_height)]).areas(area);
let header = Row::new(["Network", "Router", "Heard", ""]).style(theme.accent());
frame.render_widget(
Table::new(rows, widths).header(header).column_spacing(1),
table,
);
if note_height > 0 {
let note_text = Paragraph::new(Line::styled(text, theme.warn())).wrap(Wrap { trim: true });
frame.render_widget(note_text, note);
}
}