use super::{Aim, Model};
use crate::reply::roles::RoleRow;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Tuning {
Rows,
Editing(Edit),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Edit {
pub role: String,
pub provider: String,
pub model: String,
}
impl Edit {
pub fn of(row: &RoleRow) -> Self {
Self {
role: row.role.clone(),
provider: row.provider.clone(),
model: row.model.clone(),
}
}
pub fn ready(&self) -> bool {
!self.provider.trim().is_empty() && !self.model.trim().is_empty()
}
}
impl Model {
pub fn begin_tuning(&mut self) {
if self.aim.is_some() {
self.tuning = Some(Tuning::Rows);
}
}
pub fn close_tuning(&mut self) {
self.tuning = None;
}
pub fn edit_assignment(&mut self, row: &RoleRow) {
if self.tuning.is_some() {
self.tuning = Some(Tuning::Editing(Edit::of(row)));
}
}
pub fn cancel_assignment(&mut self) {
if self.tuning.is_some() {
self.tuning = Some(Tuning::Rows);
}
}
pub fn editing(&self, role: &str) -> Option<Edit> {
match &self.tuning {
Some(Tuning::Editing(edit)) if edit.role == role => Some(edit.clone()),
_ => None,
}
}
pub fn draft_assignment(&mut self) -> Option<&mut Edit> {
match &mut self.tuning {
Some(Tuning::Editing(edit)) => Some(edit),
_ => None,
}
}
pub fn post_effort(&mut self, role: &str, level: Option<String>) {
self.tune(&|address| crate::verbs::effort(address, role.to_owned(), level.clone()));
}
pub fn post_priority(&mut self, role: &str, on: bool) {
self.tune(&|address| crate::verbs::priority(address, role.to_owned(), on));
}
pub fn post_assignment(&mut self) {
let Some(edit) = self.draft_assignment().filter(|edit| edit.ready()).cloned() else {
return;
};
self.tune(&|address| {
crate::verbs::model(
address,
edit.role.clone(),
edit.provider.trim().to_owned(),
edit.model.trim().to_owned(),
)
});
self.cancel_assignment();
}
fn tune(&mut self, gesture: &dyn Fn(String) -> serde_json::Value) {
let Some(aim) = self.aim.clone() else {
return;
};
let Aim { address, .. } = aim;
self.outbox.push(super::Posted::act(gesture(address)));
}
}
#[cfg(test)]
mod tests;