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

fn alu_with_a_and_m(a: Decimal, m: Decimal) -> (DefaultAlu, mpsc::Receiver<Message>) {
    let memory = MemoryBuilder::new()
        .with_a(a)
        .with_m(m)
        .with_ip(1)
        .build();

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

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

    (alu, receiver)
}

#[test]
pub fn copying_an_integer_value_set_m_to_0() {
    
    // Arrange

    let (mut alu, _receiver) = alu_with_a_and_m(1u8.into(), 2u8.into());

    // Act

    let result = alu.copy_decimal();

    // Assert

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

#[test]
pub fn  m_should_have_the_same_decimal_part_as_a() {
    // Arrange

    let (mut alu, _receiver) = alu_with_a_and_m(Decimal::new(1_1, 1), 2u8.into());

    // Act

    let result = alu.copy_decimal();

    // Assert

    assert_eq!(Ok(()), result);
    assert_eq!(Decimal::new(0_1, 1), alu.memory.m.read());
    assert_eq!(2, alu.memory.ip);
}

#[test]
pub fn m_should_respect_the_a_sign() {
    // Arrange

    let (mut alu, _receiver) = alu_with_a_and_m(Decimal::new(-1_1, 1), 2u8.into());

    // Act

    let result = alu.copy_decimal();

    // Assert

    assert_eq!(Ok(()), result);
    assert_eq!(Decimal::new(-0_1, 1), alu.memory.m.read());
    assert_eq!(2, alu.memory.ip);
}
