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
use std::process::exit;

use crate::error;
pub static mut EASY_MODE: bool = false;
pub static mut TOGGLE_CASE: i32 = 0;
#[derive(PartialEq, Debug)]
pub struct ParsedArgs {
    pub repl: bool,   // inerative mode
    pub file: String, // file to read/write
    pub force: bool,  // if true, overwrites file
    pub log: bool,    // if true, logs to file
}

impl ParsedArgs {
    const fn new(repl: bool, file: String) -> Self {
        Self {
            repl,
            file,
            force: false,
            log: false,
        }
    }
}

pub fn get_string_args(args: &[String]) -> (usize, ParsedArgs) {
    let mut to_return: ParsedArgs = ParsedArgs::new(false, String::from(""));
    let mut index: usize = 1; // start at 1 because index  0 is the program name
    if args.len() < 2 {
        // if there are no arguments run in repl mode with no file
        return (0, ParsedArgs::new(true, String::from("")));
    } else if args[1].ends_with(".umpl") {
        // make sure it's a .umpl file
        to_return.file = args[1].to_string(); // if it is, then set file to the file name
        to_return.repl = false; // and set repl to false
        index += 1; // and increment index
        let file_len = to_return.file.strip_suffix(".umpl").unwrap().len(); // get the length of the file name without the .umpl
        if args.len() > 2 && args[2] == format!("{}", file_len) {
            unsafe {
                EASY_MODE = true;
            }
            index += 1; // and increment index
        } else if args.len() > 2 && args[2] == "show_length" {
            println!("{}", file_len); // print the length of the file name without the .umpl
            exit(1);
        }
    } else {
        to_return.repl = true; // if it's not a .umpl file, then set repl to true
        for (arg_index, arg) in args[index..].iter().enumerate() {
            if arg.starts_with('-') {
                // if it starts with a dash
                index += arg_index; // then add the args index to the current index
                break; // and break
            }
            usage(); // if not a flag, then its not one of the args we want so print usage and exit
        }
    };
    (index, to_return)
}

pub fn get_dash_args(args: &[String], start_index: usize, args_struct: &mut ParsedArgs) {
    args[start_index..].iter().for_each(|arg| {
        // for each arg after the start index
        if arg.starts_with('-') {
            // if it starts with a dash check if its a correct flag and set the appropriate field if not print usage and exit
            for char_part_arg in arg.chars().skip(1) {
                if ['r', 'i'].contains(&char_part_arg) {
                    args_struct.repl = true;
                } else if ['f'].contains(&char_part_arg) {
                    args_struct.force = true;
                } else if ['l'].contains(&char_part_arg) {
                    args_struct.log = true;
                } else if char_part_arg == 'e' {
                    unsafe {
                        EASY_MODE = false;
                    }
                    let num = match &args_struct.file {
                        // TODO: use rand
                        file if file.is_empty() => 0,
                        file => file.len(),
                    };
                    unsafe { TOGGLE_CASE = num as i32 };
                } else if char_part_arg == 't' {
                    let number: i32 = match arg.split_once('=') {
                        Some(n) => match n.1.parse() {
                            Ok(value) => value,
                            Err(error) => error::error(0, error),
                        },
                        _ => error::error(0, "option t requires an =number"),
                    };
                    unsafe {
                        TOGGLE_CASE = number;
                    }
                    break;
                } else {
                    usage();
                }
            }
        } else {
            usage();
        }
    });
}

fn usage() {
    unsafe {
        if EASY_MODE {
            println!(
                "Usage: umpl [File] [OPTIONS]
        OPTIONS: 
        -r, -i: interactive mode
        -h: help
        -f: force
        -t=number: toggle case"
            );
        } else {
            eprintln!("Segmentation fault (core dumped)");
        }
    }
    exit(1);
}