typeman 0.1.2

Typing speed test with practice mode in GUI, TUI and CLI
use clap::{Parser, ValueHint};
use std::{path::PathBuf};
use serde::Deserialize;

use crate ::ui::cli::modes;

mod ui {
    pub mod cli {
        pub mod main;
        pub mod modes;
    }
    pub mod gui {
        pub mod main;
        pub mod results;
        pub mod config;
        pub mod practice;
    }
    pub mod tui {
        pub mod app;
        pub mod ui;
        pub mod r#mod;
    }
}
mod practice;
mod utils;

#[derive(Parser)]
#[command(
    name = "typeman",
    about = "Welcome to the typeman!",
    version = "1.0",
    after_long_help = "Run examples:
typeman --cli -c ./text.txt
typeman --cli -q
typeman --cli -t=30 -n=500
typeman --cli -w=50 -n=500
typeman --cli -w=50 -n=500 -p -d
typeman --gui
typeman",
    long_about = "\n
Run 'typeman --cli -c <path/to/your/file>' to test your typing on a specified text
Run 'typeman --cli -q' to test your typing on a random quote
Run 'typeman --cli -w=50 (-n=500 -p -d)' to test your typing on n most common English words, specify the -w for number of words (default is 50)
Run 'typeman --cli (-t=30 -n=500 -p -d)' to test your typing on random words for t seconds; -t sets the time limit (default is 30 seconds)
Run 'typeman (--tui)' to start the terminal-based interface

Optional:
  - Use -p to include punctuation, -d to include digits
  - Use -n to specify the number of words to type (default is 50, max is 500)
  - Use -t to set a time limit for the test (default is 30 seconds, use 0 for no limit)
  - Use -n to specify the number of top words to use (default is 500, max is 1000)
  - Use --gui for terminal-based interface
  - Use --cli for terminal-based interface

Default behavior for cli is to test typing on random words for 30 seconds with 500 most common English words.
Default mode is tui.
    "
)]

struct Cli {
    #[arg(short = 'c', long = "custom", value_name = "FILE", value_hint = ValueHint::FilePath, conflicts_with_all = &["random_quote", "time_limit", "top_words", "word_number", "gui", "tui"])]
    custom_file: Option<PathBuf>,

    #[arg(short = 'q', long = "quote", conflicts_with_all = &["custom_file", "time_limit", "top_words", "gui", "tui"])]
    random_quote: bool,

    #[arg(short = 'p', long = "punctuation", conflicts_with_all = &["custom_file", "random_quote", "gui", "tui"])]
    punctuation: bool,

    #[arg(short = 'd', long = "digits", conflicts_with_all = &["custom_file", "random_quote", "gui", "tui"])]
    digits: bool,

    #[arg(short = 't', long = "time", value_name = "SECONDS", conflicts_with_all = &["gui", "tui"])]
    time_limit: Option<Option<u64>>,

    #[arg(short = 'n', long = "top_words", value_name = "WORDS", conflicts_with_all = &["gui", "tui"])]
    top_words: Option<usize>,

    #[arg(short = 'w', long = "word_number", value_name = "WORDS", num_args = 0..=1, conflicts_with_all = &["gui", "tui"])]
    word_number: Option<Option<usize>>,

    #[arg(short = 'l', long = "level", conflicts_with_all = &["custom_file", "random_quote", "time_limit", "top_words"], conflicts_with_all = &["gui", "tui"])]
    level: Option<Option<usize>>,

    #[arg(long = "gui", conflicts_with_all = &["custom_file", "random_quote", "time_limit", "top_words", "word_number", "level", "tui", "cli"])]
    gui: bool,

    #[arg(long = "tui", conflicts_with_all = &["custom_file", "random_quote", "time_limit", "top_words", "word_number", "level", "gui", "cli"])]
    tui: bool,

    #[arg(long = "cli", conflicts_with_all = &["tui", "gui"])]
    cli: bool,
}

#[derive(Debug, Deserialize)]
pub struct Quote {
    author: String,
    text: String,
}

fn main() {
    let args = Cli::parse();

    if args.gui {
        modes::gui_main();
        return;
    }
    if args.cli {
        if let Some(path) = args.custom_file {
            modes::custom_text(&path)
        } else if args.random_quote {
            modes::quotes();
        } else if args.level.is_some() {
            modes::practice(&args);
        } else if args.word_number.is_some() && !args.time_limit.is_some() {
            modes::word_mode(&args);
        } else {
            modes::time_mode(&args);
        }
        return;
    }
    modes::tui_main();    
}