use std::io::IsTerminal;
use std::path::Path;
use std::sync::Arc;
use crate::rhei_tui::event::{EventSink, NullSink, Tee};
use crate::rhei_tui::journal::JournalSink;
use crate::rhei_tui::stdout::StdoutSink;
use crate::rhei_tui::tui::{TuiContext, TuiSink};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FrontendKind {
Tui,
Stdout,
Auto,
}
pub struct Frontend {
pub sink: Arc<dyn EventSink>,
pub is_tui: bool,
_tui: Option<Arc<TuiSink>>,
}
pub fn select_frontend(
workspace_root: &Path,
kind: FrontendKind,
parallel: u16,
total_tasks: usize,
tui_context: TuiContext,
) -> Frontend {
let want_tui = match kind {
FrontendKind::Tui => true,
FrontendKind::Stdout => false,
FrontendKind::Auto => std::io::stdout().is_terminal(),
};
let journal: Arc<dyn EventSink> = match JournalSink::open(workspace_root) {
Ok(j) => Arc::new(j),
Err(err) => {
eprintln!(
"warning: could not open transition journal at {}/runtime/transitions.log: {}",
workspace_root.display(),
err
);
Arc::new(NullSink)
}
};
if want_tui {
match TuiSink::start(parallel.max(1), total_tasks, tui_context) {
Ok(tui) => {
let tui = Arc::new(tui);
let frontend: Arc<dyn EventSink> = tui.clone();
let sink = Arc::new(Tee::new(vec![journal, frontend]));
return Frontend { sink, is_tui: true, _tui: Some(tui) };
}
Err(err) => {
eprintln!("warning: could not start TUI ({}); falling back to stdout", err);
}
}
}
let stdout: Arc<dyn EventSink> = Arc::new(StdoutSink::new());
let sink = Arc::new(Tee::new(vec![journal, stdout]));
Frontend { sink, is_tui: false, _tui: None }
}