use std::path::PathBuf;
use std::sync::Arc;
use anyhow::Context;
use chrono::Utc;
use signal_hook::consts::{SIGHUP, SIGINT, SIGTERM};
use signal_hook::iterator::Signals;
use crate::app::{Asked, Wanted};
use crate::collect::agents::Agents;
use crate::collect::changes::Reported;
use crate::config::Config;
use crate::model::snapshot::{Filter, Snapshot};
use crate::view::Notice;
#[cfg(test)]
mod fixtures;
mod armed;
mod clipboard;
mod drive;
mod due;
mod keys;
mod reload;
mod screen;
mod wire;
pub(crate) use armed::{Armed, Arming};
pub(crate) use reload::{Reload, CHECKED_EVERY};
pub type Collecting = Box<dyn FnMut(Asked) -> Option<Snapshot> + Send>;
use drive::{drive, Outstanding, Reading, View};
use screen::{Drawing, Screen};
use wire::wire;
pub fn run(
cfg: &Config,
filter: Filter,
arms: Arming,
agents: Arc<dyn Agents>,
listening_on: Option<PathBuf>,
collect: Collecting,
reload: Option<Reload>,
) -> anyhow::Result<()> {
let asked_to_stop = Signals::new([SIGHUP, SIGINT, SIGTERM])
.context("asking to be told about the signals that would otherwise kill bdi")?;
let armed = arms(cfg);
let projects: Vec<String> = armed
.iter()
.map(|project| project.project().to_string())
.collect();
let awaiting = Snapshot::awaiting(
projects.clone(),
cfg.projects_named_without_git(),
agents.name(),
cfg.scope.clone(),
filter,
Utc::now(),
);
let reported = Reported::watching(projects);
let (events, ask, panes, _socket, from_the_wiring) = wire(
reported.clone(),
agents,
listening_on,
collect,
asked_to_stop,
);
let at_startup: Vec<Notice> = from_the_wiring.into_iter().collect();
let mut outstanding = Outstanding::for_a_run(cfg.tui.unanswered_after());
let started = Utc::now();
outstanding.ask(Wanted::Everything, started);
let mut screen = Screen::showing(awaiting, panes, at_startup, Drawing::to(cfg), started)?;
screen.collecting(outstanding.awaited());
drive(
&mut screen,
&events,
&ask,
outstanding,
Reading::of(armed, reported),
&arms,
reload,
)
}