1. 4FIPS
  2. PHOTOS
  3. VIDEOS
  4. APPS
  5. CODE
  6. FORUMS
  7. ABOUT
// [NUBCO BY FIPS @ 4FIPS.COM, (c) 2021 FILIP STOKLAS, MIT-LICENSED]

use std::marker::Copy;
use std::any::type_name;
use std::num::ParseIntError;
use std::fmt::{LowerHex, Display, Octal, Binary};
use num_traits::sign::{Unsigned, Signed};
use num_traits::cast::AsPrimitive;

pub(crate) enum ConversionResult {
    Value(String),
    ValueWithWarning { value: String, warning: String },
    Error(String),
}

pub(crate) struct ConversionText {
    pub(crate) text: String,
    pub(crate) symb: String,
    pub(crate) symb_hover: String
}

pub(crate) fn convert_ui<U: 'static + Unsigned + Copy, I: Signed + AsPrimitive<U>>(ures: &Result<U, ParseIntError>, ires: &Result<I, ParseIntError>, val_to_str: &dyn Fn(U) -> String) -> ConversionResult {
    match *ures {
        Ok(uval) => ConversionResult::Value(val_to_str(uval)),
        Err(ref outer_err) => {
            match *ires {
                Ok(ival) => ConversionResult::ValueWithWarning { value: val_to_str(ival.as_()), warning: format!("Failed to parse as {}, with:\n\"{}\".\n(Parsed as {} and cast to {}.)", type_name::<U>(), outer_err, type_name::<I>(), type_name::<U>())},
                Err(_) => ConversionResult::Error(format!("❌ {}", outer_err)),
            }
        },
    }
}

pub(crate) fn convert_iu<I: 'static + Signed + Copy, U: Unsigned + AsPrimitive<I>>(ires: &Result<I, ParseIntError>, ures: &Result<U, ParseIntError>, val_to_str: &dyn Fn(I) -> String) -> ConversionResult {
    match *ires {
        Ok(ival) => ConversionResult::Value(val_to_str(ival)),
        Err(ref outer_err) => {
            match *ures {
                Ok(uval) => ConversionResult::ValueWithWarning { value: val_to_str(uval.as_()), warning: format!("Failed to parse as {}, with:\n\"{}\".\n(Parsed as {} and cast to {}.)", type_name::<I>(), outer_err, type_name::<U>(), type_name::<I>())},
                Err(_) => ConversionResult::Error(format!("❌ {}", outer_err)),
            }
        },
    }
}

impl From<ConversionResult> for ConversionText {
    fn from(result: ConversionResult) -> Self {
        match result {
            ConversionResult::Value(value) => ConversionText { text: value, symb: "".to_owned(), symb_hover: "".to_owned() },
            ConversionResult::ValueWithWarning { value, warning } => ConversionText { text: value, symb: "❗".to_owned(), symb_hover: warning },
            ConversionResult::Error(error) => ConversionText { text: error, symb: "".to_owned(), symb_hover: "".to_owned() },
        }
    }
}

pub(crate) fn val_to_hex<T: LowerHex>(val: T) -> String {
    format!("{:x}", val)
}

pub(crate) fn val_to_dec<T: Display>(val: T) -> String {
    format!("{}", val)
}

pub(crate) fn val_to_oct<T: Octal>(val: T) -> String {
    format!("{:o}", val)
}

pub(crate) fn val_to_bin<T: Binary>(val: T) -> String {
    format!("{:b}", val)
}