use super::*;

pub fn parse_number(s: &str) -> Option<Value> {
    let exp_separator: &[_] = &['e', 'E', '*'];
    let (base_part, exponent_value) = match s.find(exp_separator) {
        None => (s, 0),
        Some(loc) => {
            let (base, exp) = (&s[..loc], &s[loc + 1..]);
            let exp = match exp.chars().next() {
                Some('+') => &exp[1..],
                _ => exp,
            };
            match i64::from_str(exp.trim_start_matches('*')) {
                Ok(o) => (base, o),
                Err(_) => return None,
            }
        }
    };
    if base_part == "" {
        return None;
    }
    let (digits, decimal_offset): (String, _) = match base_part.find('.') {
        None => {
            if exponent_value >= 0 {
                return BigInt::from_str_radix(&base_part, 10).map(|i| i * 10_u32.pow(exponent_value as u32)).map(|i| Value::from(i)).ok();
            }
            else {
                (base_part.to_string(), 0)
            }
        }
        Some(loc) => {
            let (lead, trail) = (&base_part[..loc], &base_part[loc + 1..]);
            let mut digits = String::from(lead);
            digits.push_str(trail);
            (digits, trail.len() as i64)
        }
    };
    BigInt::from_str_radix(&digits, 10).map(|big_int| BigDecimal::new(big_int, decimal_offset - exponent_value)).map(|i| Value::from(i)).ok()
}

#[test]
fn test() {
    println!("{:?}", parse_number("+2**2").unwrap());
    println!("{:?}", parse_number("+2.e2").unwrap());
    println!("{:?}", parse_number("+2.0e2").unwrap());
    println!("{:?}", parse_number("+200.0").unwrap());
    println!("{:?}", BigDecimal::from_str_radix("+0.31", 10).unwrap());
    println!("{:?}", BigDecimal::from_str_radix("+0.21", 10).unwrap());
    println!("{:?}", BigDecimal::from_str_radix("+0.11", 10).unwrap());
}
