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

#[test]
pub fn copying_the_accumulator_on_itself_changes_nothing() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_ip(1)
            .build();

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

    // Act

    let result = alu.copy_to_a(Register::A);

    // Assert

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

#[test]
pub fn copying_the_m_register_alter_the_accumulator() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_m(3u8.into())
            .with_ip(1)
            .build();

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

    // Act
    
    let result = alu.copy_to_a(Register::M);

    // Assert

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

#[test]
pub fn copying_the_b_split_register_alter_the_accumulator() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_b((Decimal::new(2, 0), Decimal::new(3, 0)).into())
            .with_ip(1)
            .build();

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

    // Act
    
    let result = alu.copy_to_a(Register::b);

    // Assert

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

#[test]
pub fn copying_the_b_register_alter_the_accumulator() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_b(Decimal::new(3, 0).into())
            .with_ip(1)
            .build();

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

    // Act
    
    let result = alu.copy_to_a(Register::B);

    // Assert

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

#[test]
pub fn copying_the_c_split_register_alter_the_accumulator() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_c((Decimal::new(2, 0), Decimal::new(3, 0)).into())
            .with_ip(1)
            .build();

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

    // Act
    
    let result = alu.copy_to_a(Register::c);

    // Assert

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

#[test]
pub fn copying_the_c_register_alter_the_accumulator() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_c(Decimal::new(3, 0).into())
            .with_ip(1)
            .build();

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

    // Act
    
    let result = alu.copy_to_a(Register::C);

    // Assert

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

#[test]
pub fn copying_the_d_split_register_alter_the_accumulator() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_d((Decimal::new(2, 0), Decimal::new(3, 0)).into())
            .with_ip(1)
            .build();

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

    // Act
    
    let result = alu.copy_to_a(Register::d);

    // Assert

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

#[test]
pub fn copying_the_d_register_alter_the_accumulator() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_d(Decimal::new(3, 0).into())
            .with_ip(1)
            .build();

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

    // Act
    
    let result = alu.copy_to_a(Register::D);

    // Assert

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

#[test]
pub fn copying_the_e_split_register_alter_the_accumulator() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_e((Decimal::new(2, 0), Decimal::new(3, 0)).into())
            .with_ip(1)
            .build();

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

    // Act
    
    let result = alu.copy_to_a(Register::e);

    // Assert

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

#[test]
pub fn copying_the_e_register_alter_the_accumulator() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_e(Decimal::new(3, 0).into())
            .with_ip(1)
            .build();

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

    // Act
    
    let result = alu.copy_to_a(Register::E);

    // Assert

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

#[test]
pub fn copying_the_f_split_register_alter_the_accumulator() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_f((Decimal::new(2, 0), Decimal::new(3, 0)).into())
            .with_ip(1)
            .build();

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

    // Act
    
    let result = alu.copy_to_a(Register::f);

    // Assert

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

#[test]
pub fn copying_the_f_register_alter_the_accumulator() {

    // Arrange

    let (sender, _receiver) = mpsc::channel();
        
    let memory = MemoryBuilder::new()
            .with_a(1u8.into())
            .with_f(Decimal::new(3, 0).into())
            .with_ip(1)
            .build();

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

    // Act
    
    let result = alu.copy_to_a(Register::F);

    // Assert

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

