//! Character set definitions and conversion utilities.
//!
//! This module provides functions for parsing character set options,
//! initializing character lookup tables for active segments, and printing
//! recognized characters.

use crate::defines::{
    CHARSET_MAX, Charset, D_ALT_R, D_ALTNINE, D_ALTSEVEN, D_DECIMAL, D_EIGHT, D_FIVE, D_FOUR, D_H,
    D_HEX_A, D_HEX_C, D_HEX_E, D_HEX_F, D_HEX_b, D_HEX_c, D_HEX_d, D_J, D_L, D_MINUS, D_N, D_NINE,
    D_ONE, D_P, D_R, D_SEVEN, D_SIX, D_T, D_THREE, D_TT_WRONG_SEVEN_1, D_TT_WRONG_SEVEN_2, D_TWO,
    D_U, D_Y, D_ZERO, D_h, D_n, D_r, OMIT_DECIMAL,
};

/// Parses a string keyword into a corresponding [`Charset`] variant.
///
/// Returns `None` if the keyword is not recognized.
///
/// # Arguments
/// * `keyword` - A string slice indicating the desired character set (e.g. "full", "digits", "decimal", "hex", "tt_robot").
pub fn parse_charset(keyword: &str) -> Option<Charset> {
    let kw = keyword.to_lowercase();
    if kw.starts_with("full") {
        Some(Charset::Full)
    } else if kw.starts_with("digits") {
        Some(Charset::Digits)
    } else if kw.starts_with("decimal") {
        Some(Charset::Decimal)
    } else if kw.starts_with("hex") {
        Some(Charset::Hexadecimal)
    } else if kw.starts_with("tt_robot") {
        Some(Charset::TTRobot)
    } else {
        None
    }
}

/// Initializes and returns a lookup table mapping segment bitmasks to character representations.
///
/// The returned array contains character representation mapping for each segment value.
/// Unmapped segment values default to `'_'`.
///
/// # Arguments
/// * `cs` - The active [`Charset`] defining which characters are supported.
pub fn init_charset(cs: Charset) -> [char; CHARSET_MAX + 1] {
    let mut charset_array = ['_'; CHARSET_MAX + 1];
    match cs {
        Charset::Full => {
            charset_array[D_ZERO as usize] = '0';
            charset_array[D_ONE as usize] = '1';
            charset_array[D_TWO as usize] = '2';
            charset_array[D_THREE as usize] = '3';
            charset_array[D_FOUR as usize] = '4';
            charset_array[D_FIVE as usize] = '5';
            charset_array[D_SIX as usize] = '6';
            charset_array[D_SEVEN as usize] = '7';
            charset_array[D_ALTSEVEN as usize] = '7';
            charset_array[D_EIGHT as usize] = '8';
            charset_array[D_NINE as usize] = '9';
            charset_array[D_ALTNINE as usize] = '9';
            charset_array[D_DECIMAL as usize] = '.';
            charset_array[D_MINUS as usize] = '-';
            charset_array[D_HEX_A as usize] = 'a';
            charset_array[D_HEX_b as usize] = 'b';
            charset_array[D_HEX_C as usize] = 'c';
            charset_array[D_HEX_c as usize] = 'c';
            charset_array[D_HEX_d as usize] = 'd';
            charset_array[D_HEX_E as usize] = 'e';
            charset_array[D_HEX_F as usize] = 'f';
            charset_array[D_U as usize] = 'u';
            charset_array[D_T as usize] = 't';
            charset_array[D_L as usize] = 'l';
            charset_array[D_H as usize] = 'h';
            charset_array[D_h as usize] = 'h';
            charset_array[D_R as usize] = 'r';
            charset_array[D_ALT_R as usize] = 'r';
            charset_array[D_r as usize] = 'r';
            charset_array[D_P as usize] = 'p';
            charset_array[D_N as usize] = 'n';
            charset_array[D_n as usize] = 'n';
            charset_array[D_Y as usize] = 'y';
            charset_array[D_J as usize] = 'j';
        }
        Charset::Digits => {
            charset_array[D_ZERO as usize] = '0';
            charset_array[D_ONE as usize] = '1';
            charset_array[D_TWO as usize] = '2';
            charset_array[D_THREE as usize] = '3';
            charset_array[D_FOUR as usize] = '4';
            charset_array[D_FIVE as usize] = '5';
            charset_array[D_SIX as usize] = '6';
            charset_array[D_HEX_b as usize] = '6';
            charset_array[D_SEVEN as usize] = '7';
            charset_array[D_ALTSEVEN as usize] = '7';
            charset_array[D_EIGHT as usize] = '8';
            charset_array[D_NINE as usize] = '9';
            charset_array[D_ALTNINE as usize] = '9';
        }
        Charset::Decimal => {
            charset_array[D_ZERO as usize] = '0';
            charset_array[D_ONE as usize] = '1';
            charset_array[D_TWO as usize] = '2';
            charset_array[D_THREE as usize] = '3';
            charset_array[D_FOUR as usize] = '4';
            charset_array[D_FIVE as usize] = '5';
            charset_array[D_SIX as usize] = '6';
            charset_array[D_HEX_b as usize] = '6';
            charset_array[D_SEVEN as usize] = '7';
            charset_array[D_ALTSEVEN as usize] = '7';
            charset_array[D_EIGHT as usize] = '8';
            charset_array[D_NINE as usize] = '9';
            charset_array[D_ALTNINE as usize] = '9';
            charset_array[D_DECIMAL as usize] = '.';
            charset_array[D_MINUS as usize] = '-';
        }
        Charset::Hexadecimal => {
            charset_array[D_ZERO as usize] = '0';
            charset_array[D_ONE as usize] = '1';
            charset_array[D_TWO as usize] = '2';
            charset_array[D_THREE as usize] = '3';
            charset_array[D_FOUR as usize] = '4';
            charset_array[D_FIVE as usize] = '5';
            charset_array[D_SIX as usize] = '6';
            charset_array[D_SEVEN as usize] = '7';
            charset_array[D_ALTSEVEN as usize] = '7';
            charset_array[D_EIGHT as usize] = '8';
            charset_array[D_NINE as usize] = '9';
            charset_array[D_ALTNINE as usize] = '9';
            charset_array[D_DECIMAL as usize] = '.';
            charset_array[D_MINUS as usize] = '-';
            charset_array[D_HEX_A as usize] = 'a';
            charset_array[D_HEX_b as usize] = 'b';
            charset_array[D_HEX_C as usize] = 'c';
            charset_array[D_HEX_c as usize] = 'c';
            charset_array[D_HEX_d as usize] = 'd';
            charset_array[D_HEX_E as usize] = 'e';
            charset_array[D_HEX_F as usize] = 'f';
        }
        Charset::TTRobot => {
            charset_array[D_ZERO as usize] = '0';
            charset_array[D_ONE as usize] = '1';
            charset_array[D_TWO as usize] = '2';
            charset_array[D_THREE as usize] = '3';
            charset_array[D_FOUR as usize] = '4';
            charset_array[D_FIVE as usize] = '5';
            charset_array[D_SIX as usize] = '6';
            charset_array[D_SEVEN as usize] = '7';
            charset_array[D_TT_WRONG_SEVEN_1 as usize] = '7';
            charset_array[D_TT_WRONG_SEVEN_2 as usize] = '7';
            charset_array[D_EIGHT as usize] = '8';
            charset_array[D_NINE as usize] = '9';
            charset_array[D_MINUS as usize] = '-';
            charset_array[D_HEX_A as usize] = 'a';
            charset_array[D_HEX_b as usize] = 'b';
            charset_array[D_HEX_C as usize] = 'c';
            charset_array[D_HEX_d as usize] = 'd';
            charset_array[D_U as usize] = 'v';
            charset_array[D_T as usize] = 't';
            charset_array[D_L as usize] = 'l';
            charset_array[D_H as usize] = 'h';
            charset_array[D_R as usize] = 'r';
            charset_array[D_P as usize] = 'p';
            charset_array[D_N as usize] = 'n';
        }
    }
    charset_array
}

/// Prints the character corresponding to the recognized digit's segments.
///
/// Returns `1` if the segment pattern is unrecognized (prints `'_'`), or `0` otherwise.
///
/// # Arguments
/// * `digit` - The bitmask of active segments.
/// * `flags` - Program configuration option flags (e.g. `OMIT_DECIMAL`).
/// * `charset_array` - The character lookup table initialized by [`init_charset`].
pub fn print_digit(digit: u8, flags: u32, charset_array: &[char; CHARSET_MAX + 1]) -> i32 {
    let mut unknown_digit = 0;
    let mut c = '_';
    if (digit as usize) <= CHARSET_MAX {
        c = charset_array[digit as usize];
    }
    if c == '_' {
        unknown_digit = 1;
    }
    if !(c == '.' && (flags & OMIT_DECIMAL != 0)) {
        print!("{}", c);
    }
    unknown_digit
}
