use std::time::Instant;
use crate::terminal::colors;
use crate::terminal::input;
use crate::terminal::print::Print;
use crate::terminal::spinner::SpinnerGuard;
use colored::*;
use dashmap::DashMap;
use std::net::IpAddr;
use std::sync::Arc;
use tracing::info_span;
use zond_engine::core::config::ZondConfig;
use zond_engine::core::models::host::Host;
use zond_engine::core::parse;
use zond_engine::scanner;
use zond_engine::system::interface;
pub async fn discover(targets: &[String], cfg: &ZondConfig) -> anyhow::Result<()> {
Print::header("performing host discovery");
let ip_set = parse::to_ipset(targets, Some(interface::resolve::resolve))?;
let start_time = Instant::now();
let (session, scan_task) = scanner::discover(ip_set, cfg).await?;
let _input_guard = input::start_listener(session.handle.clone());
let _guard: SpinnerGuard = run_spinner(session.store.clone());
scan_task.await??;
let mut hosts: Vec<Host> = session.store.iter().map(|kv| kv.value().clone()).collect();
if hosts.is_empty() {
Print::no_results();
return Ok(());
}
hosts.sort_by_key(|host| *host.ips().iter().next().unwrap_or(&host.primary_ip()));
Print::header("Network Discovery");
Print::hosts(&hosts)?;
Print::discovery_summary(hosts.len(), start_time.elapsed());
Ok(())
}
fn run_spinner(store: Arc<DashMap<IpAddr, Host>>) -> SpinnerGuard {
let span = info_span!("discover", indicatif.pb_show = true);
let _enter = span.enter();
SpinnerGuard::with_status(span.clone(), move || {
let count = store.len();
let count_str = count.to_string().green().bold();
let label = if count == 1 { "host" } else { "hosts" };
format!("Identified {} {} so far...", count_str, label)
.color(colors::TEXT_DEFAULT)
.italic()
})
}