mod types_misc;
mod types_string;
mod types_id;

use types_id::{smn_id_form::FormID, smn_id_global::GlobalID};
use types_misc::smn_version::Version;
use types_string::{smn_str_lrg::StrLrg, smn_str_min::StrMin, smn_str_sml::StrSml};

// ----- ----- Type Structure Rules ----- -----

// ----- Type Explanation -----
// Brief explanation of the type and its purpose.

// ----- Strucutre -----
// The internal structure of the type.

// ----- Conversion: From -----
// Implementation of the TryFrom trait for the type.

// ----- Conversion: To -----
// Implementation of the to_x functions for the type.

// ----- Getters -----
// Implementation of getter functions for the type.

// ----- Binary Conversion -----
// Implementation of functions to convert the type to and from binary data.

// Rules:
// - Each type is internally represented by a Vec<u8>
// - Froms are always type TryFrom for validation
// - Tos are always functions named to_x and should be direct returns not Result
// - Types should always be checked before to_x functions are called.
// - Always include get_bytecount function to get the bytecount of the type.


fn main() {
    test_str_sml();
    test_str_lrg();
    test_str_min();
    test_version();
    test_formid();
    test_globalid();
}

fn test_str_sml() {
    println!("Testing: StrSml");

    let str_sml_from_bytes = StrSml::from_bytes(&[
        13, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 44, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0,100, 0, 33, 0
    ]);
    let str_sml_from_str = StrSml::try_from("Γειά σου, Κόσμε!").unwrap();
    let str_sml_from_vec = StrSml::try_from(vec![
        13, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 44, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0,100, 0, 33, 0,
    ])
    .unwrap();

    println!("String from bytes: {}", str_sml_from_bytes.to_string());
    println!("String from string: {}", str_sml_from_str.to_string());
    println!("String from vec: {}", str_sml_from_vec.to_string());

    println!("Vec from bytes: {:?}", str_sml_from_bytes.to_vec());
    println!("Vec from string: {:?}", str_sml_from_str.to_vec());
    println!("Vec from vec: {:?}", str_sml_from_vec.to_vec());

    println!("Length from bytes: {}", str_sml_from_bytes.get_len());
    println!("Length from string: {}", str_sml_from_str.get_len());
    println!("Length from vec: {}", str_sml_from_vec.get_len());

    println!("Data from bytes: {:?}", str_sml_from_bytes.get_data());
    println!("Data from string: {:?}", str_sml_from_str.get_data());
    println!("Data from vec: {:?}", str_sml_from_vec.get_data());

    println!("Bytes from bytes: {:?}", str_sml_from_bytes.to_bytes());
    println!("Bytes from string: {:?}", str_sml_from_str.to_bytes());
    println!("Bytes from vec: {:?}", str_sml_from_vec.to_bytes());
        
    println!("Bytecount from bytes: {}", str_sml_from_bytes.get_bytecount());
    println!("Bytecount from string: {}",str_sml_from_str.get_bytecount());
    println!("Bytecount from vec: {}", str_sml_from_vec.get_bytecount());

    println!();
}

fn test_str_lrg() {
    println!("Testing: StrLrg");

    let str_lrg_from_bytes = StrLrg::from_bytes(&[
        13, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 44, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0,100, 0, 33, 0
    ]);
    let str_lrg_from_str = StrLrg::try_from("¡Hola, Mundo!").unwrap();
    let str_lrg_from_vec = StrLrg::try_from(vec![
        13, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 44, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0,100, 0, 33, 0,
    ])
    .unwrap();

    println!("String from bytes: {}", str_lrg_from_bytes.to_string());
    println!("String from string: {}", str_lrg_from_str.to_string());
    println!("String from vec: {}", str_lrg_from_vec.to_string());

    println!("Vec from bytes: {:?}", str_lrg_from_bytes.to_vec());
    println!("Vec from string: {:?}", str_lrg_from_str.to_vec());
    println!("Vec from vec: {:?}", str_lrg_from_vec.to_vec());

    println!("Bytes from bytes: {:?}", str_lrg_from_bytes.to_bytes());
    println!("Bytes from string: {:?}", str_lrg_from_str.to_bytes());
    println!("Bytes from vec: {:?}", str_lrg_from_vec.to_bytes());

    println!("Length from bytes: {}", str_lrg_from_bytes.get_len());
    println!("Length from string: {}", str_lrg_from_str.get_len());
    println!("Length from vec: {}", str_lrg_from_vec.get_len());

    println!("Bytecount from bytes: {:?}", str_lrg_from_bytes.get_bytecount());
    println!("Bytecount from string: {}",str_lrg_from_str.get_bytecount());
    println!("Bytecount from vec: {}", str_lrg_from_vec.get_bytecount());

    println!();
}

fn test_str_min() {
    println!("Testing: StrMin");

    let str_min_from_bytes = StrMin::from_bytes(&[
        13, 72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33,
    ]);
    let str_min_from_str = StrMin::try_from("Hello, World!").unwrap();
    let str_min_from_vec = StrMin::try_from(vec![
        13, 72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33,
    ])
    .unwrap();

    println!("String from bytes: {}", str_min_from_bytes.to_string());
    println!("String from string: {}", str_min_from_str.to_string());
    println!("String from vec: {}", str_min_from_vec.to_string());

    println!("Vec from bytes: {:?}", str_min_from_bytes.to_vec());
    println!("Vec from string: {:?}", str_min_from_str.to_vec());
    println!("Vec from vec: {:?}", str_min_from_vec.to_vec());

    println!("Bytes from bytes: {:?}", str_min_from_bytes.to_bytes());
    println!("Bytes from string: {:?}", str_min_from_str.to_bytes());
    println!("Bytes from vec: {:?}", str_min_from_vec.to_bytes());

    println!("Length from bytes: {}", str_min_from_bytes.get_len());
    println!("Length from string: {}", str_min_from_str.get_len());
    println!("Length from vec: {}", str_min_from_vec.get_len());

    println!("Data from bytes: {:?}", str_min_from_bytes.get_data());
    println!("Data from string: {:?}", str_min_from_str.get_data());
    println!("Data from vec: {:?}", str_min_from_vec.get_data());

    println!("Bytecount from bytes: {}", str_min_from_bytes.get_bytecount());
    println!("Bytecount from string: {}", str_min_from_str.get_bytecount());
    println!("Bytecount from vec: {}", str_min_from_vec.get_bytecount());

    println!();
}

fn test_version() {
    println!("Testing: Version");

    let version_from_bytes = Version::from_bytes([1, 2]);
    let version_from_vec = Version::try_from(vec![1, 2]).unwrap();
    let version_from_float = Version::try_from(2.4).unwrap();
    let version_from_str = Version::try_from("3.6").unwrap();

    println!("String from bytes: {}", version_from_bytes.to_string());
    println!("String from vec: {}", version_from_vec.to_string());
    println!("String from float: {}", version_from_float.to_string());
    println!("String from string: {}", version_from_str.to_string());

    println!("Vec from bytes: {:?}", version_from_bytes.to_vec());
    println!("Vec from vec: {:?}", version_from_vec.to_vec());
    println!("Vec from float: {:?}", version_from_float.to_vec());
    println!("Vec from string: {:?}", version_from_str.to_vec());

    println!("Float from bytes: {}", version_from_bytes.to_float());
    println!("Float from vec: {}", version_from_vec.to_float());
    println!("Float from float: {}", version_from_float.to_float());
    println!("Float from string: {}", version_from_str.to_float());

    println!("Major from bytes: {}", version_from_bytes.get_major());
    println!("Major from vec: {}", version_from_vec.get_major());
    println!("Major from float: {}", version_from_float.get_major());
    println!("Major from string: {}", version_from_str.get_major());

    println!("Minor from bytes: {}", version_from_bytes.get_minor());
    println!("Minor from vec: {}", version_from_vec.get_minor());
    println!("Minor from float: {}", version_from_float.get_minor());
    println!("Minor from string: {}", version_from_str.get_minor());

    println!("Bytes from bytes: {:?}", version_from_bytes.to_bytes());
    println!("Bytes from vec: {:?}", version_from_vec.to_bytes());
    println!("Bytes from float: {:?}", version_from_float.to_bytes());
    println!("Bytes from string: {:?}", version_from_str.to_bytes());

    println!("Bytecount from bytes: {}", version_from_bytes.get_bytecount());
    println!("Bytecount from vec: {}", version_from_vec.get_bytecount());
    println!("Bytecount from float: {}", version_from_float.get_bytecount());
    println!("Bytecount from string: {}", version_from_str.get_bytecount());


    

    println!();
}

fn test_formid() {
    println!("Testing: FormID");

    let formid_from_bytes = FormID::from_bytes([0x31, 0xD4]);
    let formid_from_vec = FormID::try_from(vec![0x31, 0xD4]).unwrap();
    let formid_from_str = FormID::try_from("54321").unwrap();
    let formid_from_hex = FormID::try_from("0xD431").unwrap();
    let formid_from_u16 = FormID::try_from(54321).unwrap();

    println!("String from bytes: {}", formid_from_bytes.to_string());
    println!("String from vec: {}", formid_from_vec.to_string());
    println!("String from string: {}", formid_from_str.to_string());
    println!("String from hex: {}", formid_from_hex.to_string());
    println!("String from u16: {}", formid_from_u16.to_string());

    println!("Hex from bytes: {}", formid_from_bytes.to_hex());
    println!("Hex from vec: {}", formid_from_vec.to_hex());
    println!("Hex from string: {}", formid_from_str.to_hex());
    println!("Hex from hex: {}", formid_from_hex.to_hex());
    println!("Hex from u16: {}", formid_from_u16.to_hex());

    println!("Vec from bytes: {:?}", formid_from_bytes.to_vec());
    println!("Vec from vec: {:?}", formid_from_vec.to_vec());
    println!("Vec from string: {:?}", formid_from_str.to_vec());
    println!("Vec from hex: {:?}", formid_from_hex.to_vec());
    println!("Vec from u16: {:?}", formid_from_u16.to_vec());

    println!("u16 from bytes: {}", formid_from_bytes.to_u16());
    println!("u16 from vec: {}", formid_from_vec.to_u16());
    println!("u16 from string: {}", formid_from_str.to_u16());
    println!("u16 from hex: {}", formid_from_hex.to_u16());
    println!("u16 from u16: {}", formid_from_u16.to_u16());

    println!("Bytes from bytes: {:?}", formid_from_bytes.to_bytes());
    println!("Bytes from vec: {:?}", formid_from_vec.to_bytes());
    println!("Bytes from string: {:?}", formid_from_str.to_bytes());
    println!("Bytes from hex: {:?}", formid_from_hex.to_bytes());
    println!("Bytes from u16: {:?}", formid_from_u16.to_bytes());

    println!("Bytecount from bytes: {}", formid_from_bytes.get_bytecount());
    println!("Bytecount from vec: {}", formid_from_vec.get_bytecount());
    println!("Bytecount from string: {}", formid_from_str.get_bytecount());
    println!("Bytecount from u16: {}", formid_from_u16.get_bytecount());
    println!("Bytecount from hex: {}", formid_from_hex.get_bytecount());

    println!();
}

fn test_globalid(){
    println!("Testing: GlobalID");

    let globalid_from_bytes = GlobalID::from_bytes([0x01, 0x35, 0x82]);
    let globalid_from_vec = GlobalID::try_from(vec![0x01, 0x35, 0x82]).unwrap();
    let globalid_from_str = GlobalID::try_from("00133333").unwrap();
    let globalid_from_hex = GlobalID::try_from("0x018235").unwrap();
    let globalid_from_u32 = GlobalID::try_from((1, 33333)).unwrap();

    println!("String from bytes: {}", globalid_from_bytes.to_string());
    println!("String from vec: {}", globalid_from_vec.to_string());
    println!("String from string: {}", globalid_from_str.to_string());
    println!("String from hex: {}", globalid_from_hex.to_string());
    println!("String from u32: {}", globalid_from_u32.to_string());

    println!("Hex from bytes: {}", globalid_from_bytes.to_hex());
    println!("Hex from vec: {}", globalid_from_vec.to_hex());
    println!("Hex from string: {}", globalid_from_str.to_hex());
    println!("Hex from hex: {}", globalid_from_hex.to_hex());
    println!("Hex from u32: {}", globalid_from_u32.to_hex());

    println!("Vec from bytes: {:?}", globalid_from_bytes.to_vec());
    println!("Vec from vec: {:?}", globalid_from_vec.to_vec());
    println!("Vec from string: {:?}", globalid_from_str.to_vec());
    println!("Vec from hex: {:?}", globalid_from_hex.to_vec());
    println!("Vec from u32: {:?}", globalid_from_u32.to_vec());

    println!("Archive ID from bytes: {}", globalid_from_bytes.get_archive_id());
    println!("u32 from vec: {}", globalid_from_vec.to_u32());
    println!("u32 from string: {}", globalid_from_str.to_u32());
    println!("u32 from hex: {}", globalid_from_hex.to_u32());
    println!("u32 from u32: {}", globalid_from_u32.to_u32());

    println!("FormID from bytes: {}", globalid_from_bytes.get_formid().to_string());
    println!("FormID from vec: {}", globalid_from_vec.get_formid().to_string());
    println!("FormID from string: {}", globalid_from_str.get_formid().to_string());
    println!("FormID from hex: {}", globalid_from_hex.get_formid().to_string());
    println!("FormID from u32: {}", globalid_from_u32.get_formid().to_string());

    println!("Bytes from bytes: {:?}", globalid_from_bytes.to_bytes());
    println!("Bytes from vec: {:?}", globalid_from_vec.to_bytes());
    println!("Bytes from string: {:?}", globalid_from_str.to_bytes());
    println!("Bytes from hex: {:?}", globalid_from_hex.to_bytes());
    println!("Bytes from u32: {:?}", globalid_from_u32.to_bytes());

    println!("Bytecount from bytes: {}", globalid_from_bytes.get_bytecount());
    println!("Bytecount from vec: {}", globalid_from_vec.get_bytecount());
    println!("Bytecount from string: {}", globalid_from_str.get_bytecount());
    println!("Bytecount from u32: {}", globalid_from_u32.get_bytecount());
    println!("Bytecount from hex: {}", globalid_from_hex.get_bytecount());

    println!();
    
}
