use crate::alu::*;
use std::sync::mpsc;
use rust_decimal::Decimal;

#[test]
pub fn an_integer_gets_a_zero_fractional_part() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();

    let memory = MemoryBuilder::new()
        .with_precision(2)
        .build();

    let alu = DefaultAlu::new_with_memory(sender, memory);

    let d = Decimal::new(314, 0);

    // Act

    let v = alu.round_off(d);

    // Assert

    assert_eq!(d.trunc(), v.trunc());
    assert_eq!(d.fract(), v.fract());
}

#[test]
pub fn numbers_with_a_precision_lower_than_required_are_right_zero_padded() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();

    let memory = MemoryBuilder::new()
        .with_precision(2)
        .build();

    let alu = DefaultAlu::new_with_memory(sender, memory);

    let d = Decimal::new(314, 1);

    // Act

    let v = alu.round_off(d);
    
    // Assert

    assert_eq!(d.trunc(), v.trunc());
    assert_eq!(d.fract(), v.fract());
}

#[test]
pub fn numbers_with_the_precision_are_not_updated() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();

    let memory = MemoryBuilder::new()
        .with_precision(2)
        .build();

    let alu = DefaultAlu::new_with_memory(sender, memory);

    let d = Decimal::new(314, 2);

    // Act

    let v = alu.round_off(d);
    
    // Assert

    assert_eq!(d.trunc(), v.trunc());
    assert_eq!(d.fract(), v.fract());
}

#[test]
pub fn rounding_provides_the_correct_number_of_decimals() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();

    let memory = MemoryBuilder::new()
        .with_precision(2)
        .build();

    let alu = DefaultAlu::new_with_memory(sender, memory);

    let d = Decimal::new(314, 2);

    // Act & assert

    let v1 = alu.round_off(Decimal::new(31415, 4));
    
    assert_eq!(d.trunc(), v1.trunc());
    assert_eq!(d.fract(), v1.fract());

    let v2 = alu.round_off(Decimal::new(3141592653589793, 15));
    
    assert_eq!(d.trunc(), v2.trunc());
    assert_eq!(d.fract(), v2.fract());
}
