1use wasm_bindgen::prelude::*;
2use wasm_bindgen::JsCast;
3use wasm_bindgen_futures;
4use web_sys::HtmlInputElement;
5use web_sys::HtmlTextAreaElement;
6use web_sys::HtmlElement;
7use starfish::*;
8use js_sys;
9
10static mut RUNNING: bool = false;
11static mut RUN_COUNT: usize = 0;
12static mut INPUT_READY: bool = false;
13
14#[wasm_bindgen]
15extern {
16 fn getScriptVar() -> String;
17
18 #[wasm_bindgen(js_namespace = LZString)]
19 fn compressToEncodedURIComponent(s: &str) -> String;
20
21 #[wasm_bindgen(js_namespace = LZString)]
22 fn decompressFromEncodedURIComponent(s: &str) -> String;
23}
24
25#[wasm_bindgen]
26pub fn run() {
27 let script = getScriptVar();
28 if &script != "" {
29 let window = web_sys::window().unwrap();
30 let document = window.document().unwrap();
31 let script_box = get_textarea_element_by_id(&document, "script");
32 script_box.set_value(&decompressFromEncodedURIComponent(&script));
33 }
34}
35
36fn create_box(code_box: &CodeBox) -> String {
37 let mut output = String::from("<pre><br>");
38 let code_box = code_box.code_box();
39 for y in 0..code_box.len() {
40 for x in 0..code_box[y].len() {
41 if x != 0 || y != 0 {
42 output.push_str(&format!("<c id=\"{}x{}\">", x, y));
43 } else {
44 output.push_str(&format!("<c id=\"{}x{}\" class=\"s\">", x, y));
45 }
46 output.push(code_box[y][x] as char);
47 output.push_str("</c>");
48 }
49 output.push_str("<br>");
50 }
51 output.push_str("<br></pre>");
52 return output;
53}
54
55fn get_input_element_by_id(document: &web_sys::Document, id: &str) -> HtmlInputElement {
56 document.get_element_by_id(id).unwrap().
57 dyn_into::<HtmlInputElement>().unwrap()
58}
59
60fn get_textarea_element_by_id(document: &web_sys::Document, id: &str) -> HtmlTextAreaElement {
61 document.get_element_by_id(id).unwrap().
62 dyn_into::<HtmlTextAreaElement>().unwrap()
63}
64
65fn get_html_element_by_id(document: &web_sys::Document, id: &str) -> HtmlElement {
66 document.get_element_by_id(id).unwrap().
67 dyn_into::<HtmlElement>().unwrap()
68}
69
70#[wasm_bindgen]
71pub fn share_script() {
72 let window = web_sys::window().unwrap();
73 let document = window.document().unwrap();
74
75 let mut url = window.location().href().unwrap();
76 if url.contains("?") {
77 url = url.split("?").next().unwrap().to_string();
78 }
79
80 let share_field = get_input_element_by_id(&document, "sharefield");
81 url.push_str("?script=");
82 url.push_str(&compressToEncodedURIComponent(&get_textarea_element_by_id(&document, "script").value()));
83 share_field.set_value(&url);
84
85 let share_box = document.get_element_by_id("sharebox").unwrap();
86 _ = share_box.set_attribute("style", "");
87}
88
89async fn sleep(ms: i32) -> Result<JsValue, JsValue> {
90 let promise = js_sys::Promise::new(&mut |resolve, _| {
91 web_sys::window()
92 .unwrap()
93 .set_timeout_with_callback_and_timeout_and_arguments_0(&resolve, ms)
94 .unwrap();
95 });
96 let result = wasm_bindgen_futures::JsFuture::from(promise).await?;
97 Ok(result)
98}
99
100#[wasm_bindgen]
101pub fn stop_script() {
102 unsafe {
103 RUN_COUNT += 1;
104 }
105}
106
107#[wasm_bindgen]
108pub fn collect_input() {
109 let window = web_sys::window().unwrap();
110 let document = window.document().unwrap();
111
112 let input_input = get_textarea_element_by_id(&document, "inputfield");
113 let input_box = get_html_element_by_id(&document, "input");
114
115 let mut out_text = input_box.inner_text();
116 out_text.push_str(&input_input.value());
117
118 input_box.set_inner_text(&out_text);
119 input_input.set_value("");
120
121 unsafe {
122 INPUT_READY = true;
123 }
124}
125
126#[wasm_bindgen]
127pub async fn run_script() {
128 let my_count: usize;
129 unsafe {
130 if RUNNING {
131 return
132 }
133 RUNNING = true;
134 my_count = RUN_COUNT;
135 }
136
137 let window = web_sys::window().unwrap();
138 let document = window.document().unwrap();
139
140 let out_box = get_html_element_by_id(&document, "output");
141 out_box.set_inner_text("");
142 let mut out_string = String::new();
143
144 let stack_box = get_html_element_by_id(&document, "stack");
145
146 let stack = Stack::from_string(&get_input_element_by_id(&document, "initialstack").value()).unwrap_or(Stack::new(None));
147 let mut code_box = starfish::CodeBox::new(&get_textarea_element_by_id(&document, "script").value(), stack, false);
148 let delay: i32 = get_input_element_by_id(&document, "delay").value().parse().unwrap_or(0);
149
150 let code_box_elem = get_html_element_by_id(&document, "codebox");
151 code_box_elem.set_inner_html(&create_box(&code_box));
152
153 let mut end = false;
154 let mut output: Option<String>;
155 let mut sleep_ms: f64;
156
157 let mut last_x: usize = 0;
158 let mut last_y: usize = 0;
159
160 let input_box = get_html_element_by_id(&document, "input");
161
162 while !end {
163 unsafe {
164 if INPUT_READY {
165 INPUT_READY = false;
166 let input_text = input_box.inner_text();
167 code_box.inject_input(input_text.as_bytes().to_vec());
168 input_box.set_inner_text("");
169 }
170 }
171
172 (output, end, sleep_ms) = code_box.swim();
173 match output {
174 Some(val) => {
175 if val.as_bytes()[0] == 13 {
176 out_string = String::new();
177 } else {
178 out_string.push_str(&val);
179 }
180 out_box.set_inner_text(&out_string);
181 },
182 None => {}
183 }
184
185 if sleep_ms > 0.0 {
186 _ = sleep(sleep_ms as i32).await;
187 }
188 if delay > 0 {
189 _ = sleep(delay).await;
190 }
191
192 unsafe {
193 if my_count != RUN_COUNT {
194 break;
195 }
196 }
197
198 if sleep_ms > 0.0 || delay > 0 {
199 if !end {
200 let last_pos = document.get_element_by_id(&format!("{}x{}", last_x, last_y)).unwrap();
201 _ = last_pos.set_attribute("class", "");
202 (last_x, last_y) = code_box.position();
203 let cur_pos = document.get_element_by_id(&format!("{}x{}", last_x, last_y)).unwrap();
204 if code_box.deep_sea() {
205 _ = cur_pos.set_attribute("class", "u");
206 } else {
207 _ = cur_pos.set_attribute("class", "s");
208 }
209 }
210
211 stack_box.set_inner_text(&code_box.string_stack());
212 }
213 }
214
215 unsafe {
216 RUNNING = false;
217 }
218}