use crate::app::event::Event;
use crate::app::state::{Consumed, SessionHelper, SessionState};
use crate::app::DynError;
use crate::sketchbook::data_structs::SketchData;
use crate::sketchbook::event_utils::{make_reversible, make_state_change};
use crate::sketchbook::{JsonSerde, Sketch};
use std::fs::File;
use std::io::Read;
const MODEL_PATH: &str = "model";
const OBSERVATIONS_PATH: &str = "observations";
const PROPERTIES_PATH: &str = "properties";
const NEW_SKETCH_PATH: &str = "new_sketch";
const EXPORT_SKETCH_PATH: &str = "export_sketch";
const EXPORT_AEON_PATH: &str = "export_aeon";
const IMPORT_SKETCH_PATH: &str = "import_sketch";
const IMPORT_AEON_PATH: &str = "import_aeon";
const IMPORT_SBML_PATH: &str = "import_sbml";
const CHECK_CONSISTENCY_PATH: &str = "check_consistency";
const ASSERT_CONSISTENCY_PATH: &str = "assert_consistency";
const SET_ANNOTATION_PATH: &str = "set_annotation";
const GET_WHOLE_SKETCH_PATH: &str = "get_whole_sketch";
impl SessionHelper for Sketch {}
impl SessionState for Sketch {
fn perform_event(&mut self, event: &Event, at_path: &[&str]) -> Result<Consumed, DynError> {
if let Some(at_path) = Self::starts_with(MODEL_PATH, at_path) {
self.model.perform_event(event, at_path)
} else if let Some(at_path) = Self::starts_with(OBSERVATIONS_PATH, at_path) {
self.observations.perform_event(event, at_path)
} else if let Some(at_path) = Self::starts_with(PROPERTIES_PATH, at_path) {
self.properties.perform_event(event, at_path)
} else if Self::starts_with(NEW_SKETCH_PATH, at_path).is_some() {
self.set_to_empty();
let sketch_data = SketchData::new_from_sketch(self);
let state_change = make_state_change(&["sketch", "set_all"], &sketch_data);
Ok(Consumed::Irreversible {
state_change,
reset: true,
})
} else if Self::starts_with(EXPORT_SKETCH_PATH, at_path).is_some() {
let path = Self::clone_payload_str(event, "sketch")?;
self.export_to_custom_json(&path)?;
Ok(Consumed::NoChange)
} else if Self::starts_with(EXPORT_AEON_PATH, at_path).is_some() {
let path = Self::clone_payload_str(event, "sketch")?;
self.export_to_aeon(&path)?;
Ok(Consumed::NoChange)
} else if Self::starts_with(IMPORT_SKETCH_PATH, at_path).is_some() {
let file_path = Self::clone_payload_str(event, "sketch")?;
let mut file = File::open(file_path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let sketch_data = SketchData::from_json_str(&contents)?;
self.modify_from_sketch_data(&sketch_data)?;
let state_change = make_state_change(&["sketch", "set_all"], &sketch_data);
Ok(Consumed::Irreversible {
state_change,
reset: true,
})
} else if Self::starts_with(IMPORT_AEON_PATH, at_path).is_some() {
let file_path = Self::clone_payload_str(event, "sketch")?;
let mut file = File::open(file_path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let new_sketch = Sketch::from_aeon(&contents)?;
self.modify_from_sketch(&new_sketch);
let sketch_data = SketchData::new_from_sketch(self);
let state_change = make_state_change(&["sketch", "set_all"], &sketch_data);
Ok(Consumed::Irreversible {
state_change,
reset: true,
})
} else if Self::starts_with(IMPORT_SBML_PATH, at_path).is_some() {
let file_path = Self::clone_payload_str(event, "sketch")?;
let mut file = File::open(file_path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let new_sketch = Sketch::from_sbml(&contents)?;
self.modify_from_sketch(&new_sketch);
let sketch_data = SketchData::new_from_sketch(self);
let state_change = make_state_change(&["sketch", "set_all"], &sketch_data);
Ok(Consumed::Irreversible {
state_change,
reset: true,
})
} else if Self::starts_with(CHECK_CONSISTENCY_PATH, at_path).is_some() {
let (success, message) = self.run_consistency_check();
let results = if success {
"No issues with the sketch were discovered!".to_string()
} else {
format!("There are issues with the sketch:\n\n{message}")
};
let payload = serde_json::to_string(&results).unwrap();
let state_change = Event::build(&["sketch", "consistency_results"], Some(&payload));
Ok(Consumed::Irreversible {
state_change,
reset: false,
})
} else if Self::starts_with(SET_ANNOTATION_PATH, at_path).is_some() {
let new_annotation = Self::clone_payload_str(event, "sketch")?;
let orig_annotation = self.get_annotation().to_string();
if new_annotation == orig_annotation {
return Ok(Consumed::NoChange);
}
self.set_annotation(&new_annotation);
let payload = serde_json::to_string(&new_annotation).unwrap();
let state_change = Event::build(&["sketch", "set_annotation"], Some(&payload));
let mut reverse_event = event.clone();
reverse_event.payload = Some(orig_annotation);
Ok(make_reversible(state_change, event, reverse_event))
} else if Self::starts_with(ASSERT_CONSISTENCY_PATH, at_path).is_some() {
self.assert_consistency()?;
Ok(Consumed::NoChange)
} else {
Self::invalid_path_error_generic(at_path)
}
}
fn refresh(&self, full_path: &[String], at_path: &[&str]) -> Result<Event, DynError> {
if let Some(at_path) = Self::starts_with(MODEL_PATH, at_path) {
self.model.refresh(full_path, at_path)
} else if let Some(at_path) = Self::starts_with(OBSERVATIONS_PATH, at_path) {
self.observations.refresh(full_path, at_path)
} else if let Some(at_path) = Self::starts_with(PROPERTIES_PATH, at_path) {
self.properties.refresh(full_path, at_path)
} else if Self::starts_with(GET_WHOLE_SKETCH_PATH, at_path).is_some() {
let sketch_data = SketchData::new_from_sketch(self);
Ok(Event {
path: full_path.to_vec(),
payload: Some(sketch_data.to_json_str()),
})
} else {
Self::invalid_path_error_generic(at_path)
}
}
}