1use crate::document::{Document, Documents, EMPTY_DOCUMENT};
10use crate::document_class::{self, DocumentClass};
11use crate::store::ModelStore;
12use brep_instructions::model::Target;
13use brep_render::engine_state::{document_signature, ComponentInsert};
14use serde_json::Value;
15
16pub enum Source<'a> {
18 Active,
20 Stored(&'a str),
22}
23
24pub fn new_instructions(docs: &mut Documents, store: &dyn ModelStore, source: Source<'_>, wizard: bool) -> Result<usize, String> {
28 let (key, json, name) = match source {
29 Source::Active => {
30 let key = docs
31 .active()
32 .name()
33 .map(str::to_string)
34 .ok_or("save the assembly first: instructions describe a saved revision")?;
35 let name = docs.active().title();
36 (key, docs.tab_engine().history.request_json(), name)
37 }
38 Source::Stored(key) => {
39 let json = store.read(key).ok_or_else(|| format!("no document '{key}'"))?;
40 let name = document_class::strip_class_extension(&crate::store::file_name_of(key)).to_string();
41 (key.to_string(), json, name)
42 }
43 };
44 let document: Value = serde_json::from_str(&json).map_err(|e| format!("'{key}' is not a document: {e}"))?;
45 if DocumentClass::of_document(&document) == DocumentClass::Instructions {
46 return Err("that document is already instructions; open an assembly".into());
47 }
48 let signature = document_signature(&json);
49 let target = Target {
50 source_key: key.clone(),
51 part_number: String::new(),
52 revision: String::new(),
53 signature: signature.clone(),
54 name: name.clone(),
55 };
56 let mut engine = docs.spawn_engine();
57 engine.set_history_json(EMPTY_DOCUMENT)?;
58 engine.settings.workbench = crate::workbench::instructions::INSTRUCTIONS.id.into();
60 engine.instructions_start(
61 ComponentInsert::New { name: &name, source_key: &key, source_signature: &signature, document_json: &json },
62 target,
63 )?;
64 if wizard {
65 engine.instructions_run_wizard_when_built()?;
66 }
67 Ok(docs.open_document(Document::new(engine)))
68}