use crate::constants::{
    BATS_IN_CAVE, INITIAL_ARROWS, MAX_LINKS_IN_ROOM, MAX_ROOMS_IN_CAVE, MIN_LINKS_IN_ROOM,
    MIN_ROOMS_IN_CAVE, PITS_IN_CAVE,
};
use crate::instructions::instructions;
use crate::play::game_loop;
use clap::{ColorChoice, Parser};
use std::process::exit;
use std::sync::OnceLock;

mod constants;
mod error;
mod instructions;
mod interaction;
mod map;
mod play;

#[derive(Debug, Parser)]
#[command(author, version, about, color = ColorChoice::Never)]
struct Args {
    /// Set number of arrows you will carry
    #[arg(short, long, default_value_t = INITIAL_ARROWS)]
    arrows: u32,
    /// Set number of rooms with bats in the cave
    #[arg(short, long, default_value_t = BATS_IN_CAVE)]
    bats: u32,
    /// Show debugging information
    #[arg(short, long)]
    debug: bool,
    /// Set number of rooms with pits in the cave
    #[arg(short, long, default_value_t = PITS_IN_CAVE)]
    pits: u32,
    /// Set number of rooms in cave
    #[arg(skip = 20_u32)] // short, long, default_value_t = ROOMS_IN_CAVE (20)
    rooms: u32,
    /// Set number of tunnels per room
    #[arg(skip = 3_u32)] // short = 't', long, default_value_t = LINKS_IN_ROOM (3)
    tunnels: u32,
    /// Make the game extra difficult
    #[arg(short = 'H', long)]
    hard: bool,
}

static DEBUG: OnceLock<bool> = OnceLock::new();

fn main() {
    let args = Args::parse();
    DEBUG
        .set(args.debug)
        .expect("OnceCell \"DEBUG\" was already set.");

    if let Some(amusing_error) = validate_arguments(&args) {
        eprintln!("{amusing_error}");
        exit(-1);
    }
    instructions();
    println!(
        "\nYou're in a cave with {} rooms and {} tunnels leading from each room.",
        args.rooms, args.tunnels
    );
    println!(
        "There are {} bat{} and {} pit{} scattered throughout the cave, and your",
        args.bats,
        interaction::plural(args.bats),
        args.pits,
        interaction::plural(args.pits)
    );
    println!(
        "quiver holds {} custom super anti-evil Wumpus arrows.  Good luck.",
        args.arrows
    );

    game_loop(&args).unwrap();
}

fn validate_arguments(args: &Args) -> Option<&'static str> {
    if args.rooms < MIN_ROOMS_IN_CAVE {
        Some("No self-respecting wumpus would live in such a small cave!\n")
    } else if args.rooms > MAX_ROOMS_IN_CAVE {
        Some("Even wumpii can't furnish caves that large!\n")
    } else if args.tunnels < MIN_LINKS_IN_ROOM {
        Some("Wumpii like extra doors in their caves!\n")
    } else if args.tunnels > MAX_LINKS_IN_ROOM || args.tunnels > args.rooms - (args.rooms / 4) {
        Some("Too many tunnels!  The cave collapsed!\n(Fortunately, the wumpus escaped!)\n")
    } else if args.bats > args.rooms / 2 {
        Some("The wumpus refused to enter the cave, claiming it was too crowded!\n")
    } else if args.pits > args.rooms / 2 {
        Some("The wumpus refused to enter the cave, claiming it was too dangerous!\n")
    } else {
        None
    }
}