use gemma::chip8::computer::Chip8Computer;
use gemma::constants::CHIP8_VIDEO_MEMORY;

#[test]
fn smoke() { assert!(true) }

fn load_result(to_load: &str) -> String {
    std::fs::read_to_string(format!("../resources/test/{}", to_load)).unwrap()
}

fn load_rom(to_load: &str) -> Vec<u8> {
    std::fs::read(format!("../resources/roms/{}", to_load)).unwrap()
}

#[test]
fn reset_clears_video() {
    let mut x = Chip8Computer::new();

    for i in 0..CHIP8_VIDEO_MEMORY {
        x.video_memory.poke(i as u16, i % 2 == 0);
    }

    x.reset();
    x.video_memory.reset();

    assert_eq!(x.dump_video_to_string(), x.video_memory.format_as_string());

    for i in 0..CHIP8_VIDEO_MEMORY {
        assert!(!x.video_memory.peek(i as u16));
    }
}

#[test]
fn level1_test() {
    let mut x = Chip8Computer::new();
    let level_1_rom = load_rom("1-chip8-logo.ch8");
    x.load_bytes_to_memory(0x200, (&level_1_rom).into());

    // run for 0x40 cycles
    while x.num_cycles < 0x40 {
        x.step_system();
    }
    assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_level_1_test.asc"));
}

#[test]
fn level2_test() {
    let mut x = Chip8Computer::new();
    // Load the IBM rom and run it.
    // it takes 39 cycles to get to the end so lets run it 40.
    
    let test_rom_to_run = load_rom("2-ibm-logo.ch8");
    x.load_bytes_to_memory(0x200, (&test_rom_to_run).into());

    for i in 0..40 {
        x.step_system();
    }
    // ...then verify that the current video memory of the chip-8
    // simulator matches what we expect it to be

    assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_ibm_rom_output.asc"));
}

#[test]
fn level3_test() {
    let mut x = Chip8Computer::new();

     x.load_bytes_to_memory(
         0x200, (&load_rom("3-corax+.ch8")).into()
     );
    for i in 0..0x180 {
        x.step_system();
    }

    assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_corax_plus.asc"));
}

#[test]
fn rps_test() {
    let mut x = Chip8Computer::new();
    x.load_bytes_to_memory(0x200, &load_rom("RPS.ch8").into());
    for i in 0..0xF0 {
        x.step_system();
    }
    assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_rps_stage1.asc"));
    x.keypad.push_key(0x01);
    for i in 0..0x200 {
        x.step_system();
    }
    assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_rps_stage2.asc"));
}

#[test]
fn level4_test() {
    // flags
    let mut x = Chip8Computer::new();
    x.load_bytes_to_memory(0x200, &load_rom("4-flags.ch8").into());
    for i in 0..0x400 {
        x.step_system();
    }

    assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_flags.asc"));
}
