use std::io;
use crate::backend::test::TestBackend;
use crate::ontology::OntologyRegistry;
use crate::runtime::{Command, Model};
use crate::terminal::Terminal;
use super::protocol::{AgentRequest, AgentResponse, RequestEnvelope};
use super::session::AgentSession;
pub struct HeadlessDriver<M: Model> {
model: M,
terminal: Terminal<TestBackend>,
session: AgentSession,
ontology: OntologyRegistry,
running: bool,
}
impl<M: Model> HeadlessDriver<M> {
pub fn new(model: M, width: u16, height: u16) -> io::Result<Self> {
let backend = TestBackend::new(width, height);
let terminal = Terminal::new(backend)?;
let mut ontology = OntologyRegistry::new();
model.register_ontology(&mut ontology);
Ok(Self {
model,
terminal,
session: AgentSession::new(),
ontology,
running: true,
})
}
pub fn is_running(&self) -> bool {
self.running
}
pub fn model(&self) -> &M {
&self.model
}
pub fn ontology(&self) -> &OntologyRegistry {
&self.ontology
}
pub fn session(&self) -> &AgentSession {
&self.session
}
pub fn row_text(&self, y: u16) -> String {
self.terminal.backend().row_text(y)
}
pub fn render(&mut self) -> io::Result<()> {
let model = &self.model;
self.terminal.draw(|frame| {
model.view(frame);
})
}
pub fn process_request(&mut self, request: &AgentRequest) -> AgentResponse {
let (response, should_quit) = self.session.process_request(request, &self.ontology);
if let AgentRequest::ExecuteAction {
agent_id,
action,
params,
} = request
{
let cmd = Command::AgentAction {
agent_id: agent_id.clone(),
action: action.clone(),
params: params.clone(),
};
self.process_command(cmd);
}
if let AgentRequest::InjectEvent { event } = request {
if let Some(ev) = AgentSession::convert_injected_event(event) {
if let Some(msg) = self.model.handle_event(ev) {
let cmd = self.model.update(msg);
self.process_command(cmd);
}
}
}
if should_quit {
self.running = false;
}
response
}
pub fn process_envelope(&mut self, envelope: &RequestEnvelope) -> AgentResponse {
let mut response = self.process_request(&envelope.request);
if let Some(ref id) = envelope.id {
response = response.with_id(id.clone());
}
response
}
pub fn tick(&mut self) {
if let Some(msg) = self.model.handle_event(crate::event::Event::Tick) {
let cmd = self.model.update(msg);
self.process_command(cmd);
}
}
pub fn init(&mut self) {
let cmd = self.model.init();
self.process_command(cmd);
}
fn process_command(&mut self, cmd: Command<M::Msg>) {
match cmd {
Command::None => {}
Command::Quit => {
self.running = false;
}
Command::Batch(cmds) => {
for c in cmds {
self.process_command(c);
}
}
Command::Message(msg) => {
let cmd = self.model.update(msg);
self.process_command(cmd);
}
Command::SetTickRate(_) => {
}
Command::ExportOntology => {
self.model.register_ontology(&mut self.ontology);
}
Command::AgentAction {
agent_id: _,
action: _,
params: _,
} => {
}
Command::Task(_) => {
}
}
}
}