use std::ops::Deref;
use crate::{
input::Input,
io::OpOutput,
ops::{OpWithTarget},
view::{
jmbl_view::{JMBLView, JMBLViewRef},
value::Value,
},
};
use super::{jmbl_state::ReadableJMBL, ops::ObjID};
pub struct JMBL {
pub readable: ReadableJMBL,
op_output: Option<OpOutput>,
}
impl Deref for JMBL {
type Target = ReadableJMBL;
fn deref(&self) -> &Self::Target {
&self.readable
}
}
impl JMBL {
pub fn start_changing_object(&mut self) -> JMBLViewRef {
let op_output = self.op_output.take().unwrap();
JMBLViewRef::new(JMBLView::new(
Some(op_output),
self.readable.state.clone(),
))
}
pub fn finish_changing_object(&mut self, mut write_view: JMBLViewRef) -> Vec<OpWithTarget> {
let (op_output, edit_ops) = write_view.finalize_writing();
let new_state = write_view.get().jmbl_state.clone();
self.readable = ReadableJMBL::new_from(new_state);
self.op_output = Some(op_output);
edit_ops
}
pub fn change_object<CFn: Fn(&mut Value)>(
&mut self,
obj_id: &ObjID,
changer: CFn,
) -> Vec<OpWithTarget> {
let write_view = self.start_changing_object();
changer(&mut write_view.obj_id_to_value(obj_id));
self.finish_changing_object(write_view)
}
pub fn change<CFn: Fn(&mut Value)>(&mut self, changer: CFn) -> Vec<OpWithTarget> {
let (root_id, _) = *self
.readable
.root
.as_ref()
.expect("Expected to have root to change");
self.change_object(&root_id, changer)
}
pub fn new_empty() -> JMBL {
JMBL {
readable: ReadableJMBL::new(),
op_output: None,
}
}
pub fn new_from_root<I: Into<Input>>(input: I, op_output: OpOutput) -> Self {
let mut jmbl = JMBL::new_empty();
jmbl.op_output = Some(op_output);
let mut write_view = jmbl.start_changing_object();
write_view.create_root(input);
jmbl.finish_changing_object(write_view);
jmbl
}
pub fn switch_to_new_op_output(&mut self, op_output: OpOutput) -> Self {
self.op_output = None;
JMBL {
readable: self.readable.clone(),
op_output: Some(op_output),
}
}
pub fn make_readable(&mut self) {
self.op_output = None;
}
pub fn apply_ops<'a, I: IntoIterator<Item = &'a OpWithTarget>>(&mut self, ops: I) {
self.readable = self.readable.with_ops_applied(ops);
}
pub fn test_get_past_sent_ops(&mut self) -> Option<Vec<OpWithTarget>> {
self.op_output.as_mut().unwrap().test_get_past_sent_ops()
}
}