1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
//! This module helps create the CSI sequences for `SM` and `RM`.

use crate::control::ControlSequence;

/// A struct representing an `SM` or an `RM` CSI function.
///
/// ### Examples
/// ```
/// use coded_chars::mode::mode;
///
/// // Set a mode (EXPLICIT-BDSM mode)
/// println!("{}", mode().bi_directional_support().set());
///
/// // Reset a mode (IMPLICIT-BDSM mode)
/// println!("{}", mode().bi_directional_support().reset());
/// ```
pub struct Mode {
    modes: Vec<String>,
}

impl Mode {
    pub fn new() -> Self { Self { modes: vec![] } }

    /// # GATM - Guarded area transfer mode
    ///
    /// - GUARD (set) : Only the contents of unguarded areas in an eligible area are transmitted or transferred.
    /// - ALL (reset) : The contents of guarded as well as of unguarded areas in an eligible area are transmitted or transferred.
    ///
    /// ### Note
    /// No control functions are affected.
    pub fn guarded_area_transfer(&mut self) -> &mut Self { self.add("1") }

    /// # KAM - Keyboard action mode
    ///
    /// - ENABLED (set) : All or part of the manual input facilities are enabled to be used.
    /// - DISABLED (reset) : All or part of the manual input facilities are disabled.
    ///
    /// ### Note
    /// No control functions are affected.
    pub fn keyboard_action(&mut self) -> &mut Self { self.add("2") }

    /// # CRM - Control representation mode
    ///
    /// - CONTROL (set) : All control functions are performed as defined; the way formator functions are processed depends on the
    /// setting of the FORMAT EFFECTOR ACTION MODE (FEAM). A device may choose to image the
    /// graphical representations of control functions in addition to performing them.
    /// - GRAPHIC (reset) : All control functions, except RESET MODE (RM), are treated as graphic characters. A device may
    /// choose to perform some control functions in addition to storing them and imaging their graphical
    /// representations.
    ///
    /// ### Note
    /// All control functions, except RM, are affected.
    pub fn control_representation(&mut self) -> &mut Self { self.add("3") }

    /// # IRM - Insertion replacement mode
    ///
    /// - REPLACE (set) : The graphic symbol of a graphic character or of a control function, for which a graphical representation
    /// is required, replaces (or, depending upon the implementation, is combined with) the graphic symbol
    /// imaged at the active presentation position.
    /// - INSERT (reset) : The graphic symbol of a graphic character or of a control function, for which a graphical representation
    /// is required, is inserted at the active presentation position.
    ///
    /// ### Note
    /// Only control functions for which a graphical representation is required are affected.
    pub fn insertion_replacement(&mut self) -> &mut Self { self.add("4") }

    /// # SRTM - Status report transfer mode
    ///
    /// - NORMAL (set) :  Status reports in the form of DEVICE CONTROL STRINGs (DCS) are not generated automatically.
    /// - DIAGNOSTIC (reset) : Status reports in the form of DEVICE CONTROL STRINGs (DCS) are included in every data stream transmitted or transferred.
    ///
    /// ### Note
    /// No control functions are affected.
    pub fn status_report_transfer(&mut self) -> &mut Self { self.add("5") }

    /// # ERM - Erasure mode
    ///
    /// - PROTECT (set) : Only the contents of unprotected areas are affected by an erasure control function.
    /// - ALL (reset) : The contents of protected as well as of unprotected areas are affected by an erasure control function.
    ///
    /// ### Note
    /// Control functions affected are: EA, ECH, ED, EF, EL.
    ///
    /// - [crate::editor::erase]
    /// - [crate::editor::erase_char]
    /// - [crate::editor::erase_in_page]
    /// - [crate::editor::erase_in_field]
    /// - [crate::editor::erase_in_line]
    pub fn erasure(&mut self) -> &mut Self { self.add("6") }

    /// # VEM - Line editing mode
    ///
    /// - FOLLOWING (set) :
    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, a line insertion
    ///     causes the contents of the active line (the line that contains the active presentation position) and of the
    ///     following lines in the presentation component to be shifted in the direction of the line progression; a line
    ///     deletion causes the contents of the lines following the active line to be shifted in the direction opposite
    ///     to that of the line progression.
    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, a line insertion causes the
    ///     contents of the active line (the line that contains the active data position) and of the following lines in
    ///     the data component to be shifted in the direction of the line progression; a line deletion causes the
    ///     contents of the lines following the active line to be shifted in the direction opposite to that of the line
    ///     progression.
    /// - PRECEDING (reset) :
    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, a line insertion
    ///     causes the contents of the active line (the line that contains the active presentation position) and of the
    ///     preceding lines to be shifted in the direction opposite to that of the line progression; a line deletion
    ///     causes the contents of the lines preceding the active line to be shifted in the direction of the line
    ///     progression.
    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, a line insertion causes the
    ///     contents of the active line (the line that contains the active data position) and of the preceding lines to be
    ///     shifted in the direction opposite to that of the line progression; a line deletion causes the contents of the
    ///     lines preceding the active line to be shifted in the direction of the line progression.
    ///
    /// ### Note
    /// Control functions affected are: DL, IL.
    ///
    /// - [crate::editor::delete_line]
    /// - [crate::editor::insert_line]
    pub fn line_editing(&mut self) -> &mut Self { self.add("7") }

    /// # BDSM - Bidirectional support mode
    ///
    /// - EXPLICIT (set) : Control functions are performed in the data component or in the presentation component, depending on
    /// the setting of the DEVICE COMPONENT SELECT MODE (DCSM).
    /// - IMPLICIT (reset) :  Control functions are performed in the data component. All bi-directional aspects of data are handled by
    /// the device itself.
    pub fn bi_directional_support(&mut self) -> &mut Self { self.add("8") }

    /// # DCSM -- Device component select mode
    ///
    /// - PRESENTATION (set) : Certain control functions are performed in the presentation component. The active presentation position
    /// (or the active line, where applicable) in the presentation component is the reference position against
    /// which the relevant control functions are performed.
    /// - DATA (reset) : Certain control functions are performed in the data component. The active data position (or the active
    /// line, where applicable) in the data component is the reference position against which the relevant control
    /// functions are performed
    ///
    /// ### Note
    /// Control functions affected are: CPR, CR, DCH, DL, EA, ECH, ED, EF, EL, ICH, IL, LF, NEL, RI, SLH,
    /// SLL, SPH, SPL.
    ///
    /// - [crate::cursor::position_report]
    /// - [crate::format::CR],
    /// - [crate::editor::delete_char],
    /// - [crate::editor::delete_line],
    /// - [crate::editor::erase],
    /// - [crate::editor::erase_char]
    /// - [crate::editor::erase_in_page]
    /// - [crate::editor::erase_in_field]
    /// - [crate::editor::erase_in_line]
    /// - [crate::editor::insert_char]
    /// - [crate::editor::insert_line]
    /// - [crate::format::LF],
    /// - [crate::format::NEL],
    /// - [crate::format::RI],
    /// - [crate::presentation::line_home],
    /// - [crate::presentation::line_limit],
    /// - [crate::presentation::page_home],
    /// - [crate::presentation::page_limit].
    ///
    pub fn device_component_select(&mut self) -> &mut Self { self.add("9") }

    /// # HEM - Character editing mode
    ///
    /// - FOLLOWING (set) :
    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, a character
    ///     insertion causes the contents of the active presentation position and of the following character positions
    ///     in the presentation component to be shifted in the direction of the character path; a character deletion
    ///     causes the contents of the character positions following the active presentation position to be shifted in
    ///     the direction opposite to that of the character path.
    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, a character insertion causes
    ///     the contents of the active data position and of the following character positions in the data component to
    ///     be shifted in the direction of the character progression; a character deletion causes the contents of the
    ///     character positions following the active data position to be shifted in the direction opposite to that of the
    ///     character progression.
    /// - PRECEDING (reset) :
    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, a character
    ///     insertion causes the contents of the active presentation position and of the following character positions
    ///     in the presentation component to be shifted in the direction opposite to that of the character path; a
    ///     character deletion causes the contents of the character positions following the active presentation
    ///     position to be shifted in the direction of the character path.
    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, a character insertion causes
    ///     the contents of the active data position and of preceding character positions in the data component to be
    ///     shifted in the direction opposite to that of the character progression; a character deletion causes the
    ///     contents of the character positions preceding the active data position to be shifted in the direction of the
    ///     character progression.
    ///
    /// ### Note
    /// Control functions affected are: DCH, ICH.
    ///
    /// - [crate::editor::delete_char],
    /// - [crate::editor::insert_char].
    pub fn character_editing(&mut self) -> &mut Self { self.add("10") }

    /// # SRM - Send/receive mode
    ///
    /// - MONITOR (set) : Data which are locally entered are immediately imaged.
    /// - SIMULTANEOUS (reset) : Local input facilities are logically disconnected from the output mechanism; only data which are sent to
    /// the device are imaged.
    ///
    /// ### Note
    /// No control functions are affected.
    pub fn send_receive(&mut self) -> &mut Self { self.add("12") }

    /// # FEAM - Format effector action mode
    ///
    /// - EXECUTE (set) : Formator functions are performed immediately and may be stored in addition to being performed.
    /// - STORE (reset) :Formator functions are stored but not performed. In this case, the specified action is intended to be
    /// performed by another device when the associated data are transmitted or transferred.
    ///
    /// ### Note
    /// Control functions affected are: BPH, BS, CR, DTA, FF, FNT, GCC, GSM, GSS, HPA, HPB, HPR, HT,
    /// HTJ, HTS, HVP, JFY, NEL, PEC, PFS, PLD, PLU, PPA, PPB, PPR, PTX, QUAD, RI, SACS, SAPV,
    /// SCO, SCS, SGR, SHS, SLH, SLL, SLS, SPD, SPI, SPQR, SRCS, SRS, SSU, SSW, STAB, SVS, TAC, TALE,
    /// TATE, TBC, TCC, TSS, VPA, VPB, VPR, VTS.
    pub fn format_effector_action(&mut self) -> &mut Self { self.add("13") }

    /// # FETM - Format effector transfer mode
    ///
    /// - INSERT (set) : Formator functions may be inserted in a data stream to be transmitted or in data to be transferred to an
    /// auxiliary input/output device.
    /// - EXCLUDE (reset) : No formator functions other than those received while the FORMAT EFFECTOR ACTION MODE
    /// (FEAM) is set to STORE are included in a transmitted data stream or in data transferred to an auxiliary
    /// input/output device.
    ///
    /// ### Note
    /// No control functions are affected.
    pub fn format_effector_transfer(&mut self) -> &mut Self { self.add("14") }

    /// # MATM - Multiple area transfer mode
    ///
    /// - SINGLE (set) : Only the contents of the selected area which contains the active presentation position are eligible to be
    /// transmitted or transferred.
    /// - MULTIPLE (reset) : The contents of all selected areas are eligible to be transmitted or transferred.
    ///
    /// ### Note
    /// No control functions are affected.
    pub fn multiple_area_transfer(&mut self) -> &mut Self { self.add("15") }

    /// # TTM - Transfer termination mode
    ///
    /// - CURSOR (set) : Only the contents of the character positions preceding the active presentation position in the presentation
    /// component are eligible to be transmitted or transferred.
    /// - ALL (reset) : The contents of character positions preceding, following, and at the active presentation position are
    /// eligible to be transmitted or transferred.
    ///
    /// ### Note
    /// No control functions are affected.
    pub fn transfert_termination(&mut self) -> &mut Self { self.add("16") }

    /// # SATM - Selected area transfer mode
    ///
    /// - SELECT (set) : Only the contents of selected areas are eligible to be transmitted or transferred.
    /// - ALL (reset) : The contents of all character positions, irrespective of any explicitly defined selected areas, are eligible
    /// to be transmitted or transferred.
    ///
    /// ### Note
    /// No control functions are affected.
    pub fn selected_area_transfer(&mut self) -> &mut Self { self.add("17") }

    /// # TSM - Tabulation stop mode
    ///
    /// - MULTIPLE (set) : Character tabulation stops in the presentation component are set or cleared in the active line (the line
    /// that contains the active presentation position) and in the corresponding character positions of the
    /// preceding lines and of the following lines.
    /// - SINGLE (reset) : Character tabulation stops in the presentation component are set or cleared in the active line only.
    ///
    /// ### Note
    /// Control functions affected are: CTC, DL, HTS, IL, TBC.
    ///
    /// - [crate::cursor::tabulation_control],
    /// - [crate::editor::delete_line],
    /// - [crate::format::HTS],
    /// - [crate::editor::insert_line].
    /// - [crate::format::clear_tabulation].
    pub fn tabulation_stop(&mut self) -> &mut Self { self.add("18") }
    
    /// # GRCM - Graphic rendition combination mode
    /// 
    /// - REPLACING (set) : Each occurrence of the control function SELECT GRAPHIC RENDITION (SGR) cancels the effect of
    /// any preceding occurrence. Any graphic rendition aspects that are to remain unchanged after an
    /// occurrence of SGR have to be re-specified by that SGR.
    /// - CUMULATIVE (reset) : Each occurrence of the control function SELECT GRAPHIC RENDITION (SGR) causes only those
    /// graphic rendition aspects to be changed that are specified by that SGR. All other graphic rendition
    /// aspects remain unchanged.
    /// 
    /// ### Note
    /// Control function affected is SGR : [crate::presentation::select_graphic].
    pub fn graphic_rendition_combination(&mut self) -> &mut Self { self.add("21") }

    /// # SM - Set Mode
    /// SM causes the modes of the receiving device to be set as specified.
    pub fn set(&self) -> ControlSequence {
        ControlSequence::new(&self.modes.iter().map(|s| s.as_str()).collect::<Vec<_>>(), "h")
    }

    /// # RM - Reset Mode
    /// RM causes the modes of the receiving device to be reset as specified.
    pub fn reset(&self) -> ControlSequence {
        ControlSequence::new(&self.modes.iter().map(|s| s.as_str()).collect::<Vec<_>>(), "l")
    }
    fn add(&mut self, s: &str) -> &mut Self {
        self.modes.push(s.to_string());
        self
    }
}

/// Creates a new [Mode] sequence to set or reset devices modes.
///
/// ### Example
/// ```
/// use coded_chars::mode::mode;
///
/// // Sets the DCSM mode to PRESENTATION and the HEM mode to FOLLOWING.
/// mode().device_component_select().character_editing().set().exec();
/// ```
pub fn mode() -> Mode { Mode::new() }