use crate::alu::*;
use crate::message::*;
use std::sync::mpsc;
use std::time::Duration;
use rust_decimal::Decimal;

#[test]
fn when_a_numeric_key_is_pressed_then_the_m_register_should_be_overwritten() {

    // Arrange
    
    let (sender, _system) = mpsc::channel();

    let mut alu = DefaultAlu {
        memory: MemoryBuilder::new()
            .with_m(123.into())
            .build(),
        system: sender,
        decimals: None
    };

    // Act

    let result = alu.overwrite_m(2.into());
    
    // Assert

    assert_eq!(Ok(()), result);
    assert_eq!(Decimal::new(2, 0), alu.memory.m.read());
    assert_eq!(None, alu.decimals);
}

#[test]
fn when_in_decimal_mode_a_numeric_key_is_pressed_then_the_m_register_should_be_overwritten() {

    // Arrange
    
    let (sender, _system) = mpsc::channel();

    let mut alu = DefaultAlu {
        memory: MemoryBuilder::new()
            .with_m(123.into())
            .build(),
        system: sender,
        decimals: Some(0)
    };

    // Act

    let result = alu.overwrite_m(2.into());
    
    // Assert

    assert_eq!(Ok(()), result);
    assert_eq!(Decimal::new(2, 1), alu.memory.m.read());
    assert_eq!(Some(1), alu.decimals);
}

#[test]
fn for_any_pressed_numeric_key_a_print_message_should_be_emitted() {

    // Arrange
    
    let (sender, system) = mpsc::channel();

    let mut alu = DefaultAlu {
        memory: MemoryBuilder::new()
            .with_m(123.into())
            .build(),
        system: sender,
        decimals: None
    };

    // Act

    let result = alu.overwrite_m(2.into());
    
    // Assert

    assert_eq!(Ok(()), result);
    let msg = system.recv_timeout(Duration::from_millis(1));
    assert_eq!(Ok(Message::Print("2".to_string())), msg);
}

