use crate::{Color, RenderBuffer};

use super::rom_test;

const COLOR_01: Color = Color {
    r: 0x00,
    g: 0x2A,
    b: 0x88,
};
const COLOR_16: Color = Color {
    r: 0xB5,
    g: 0x31,
    b: 0x20,
};
const COLOR_0B: Color = Color {
    r: 0x00,
    g: 0x4F,
    b: 0x08,
};

rom_test!(ppu_fill, "ppu_fill.nes", |nes| {
    assert_eq!(nes.last_instruction(), "0x802B HLT :2 []");
    assert_eq!(nes.cpu.a, 0x01);

    let mut buffer = RenderBuffer::empty();
    for l in 0..240 {
        for p in 0..256 {
            buffer.write(l, p, COLOR_01);
        }
    }
    nes.ppu().render_buffer.assert_eq(&buffer);
});

rom_test!(ppu_fill_red, "ppu_fill_red.nes", |nes| {
    assert_eq!(nes.last_instruction(), "0x803A HLT :2 []");
    assert_eq!(nes.cpu.a, 0x01);

    let mut buffer = RenderBuffer::empty();
    for l in 0..240 {
        for p in 0..256 {
            buffer.write(l, p, COLOR_16);
        }
    }
    nes.ppu().render_buffer.assert_eq(&buffer);
});

rom_test!(ppu_fill_palette_1, "ppu_fill_palette_1.nes", |nes| {
    assert_eq!(nes.last_instruction(), "0x8064 HLT :2 []");
    assert_eq!(nes.cpu.a, 0x01);

    let mut buffer = RenderBuffer::empty();
    for l in 0..240 {
        for p in 0..256 {
            if (p / 16) % 2 == (l / 16) % 2 {
                buffer.write(l, p, COLOR_01);
            } else {
                buffer.write(l, p, COLOR_16);
            }
        }
    }
    nes.ppu().render_buffer.assert_eq(&buffer);
});

rom_test!(ppu_fill_name_table, "ppu_fill_name_table.nes", |nes| {
    assert_eq!(nes.last_instruction(), "0x80B3 HLT :2 []");
    assert_eq!(nes.cpu.a, 0x01);

    let mut buffer = RenderBuffer::empty();
    for l in 0..240 {
        for p in 0..256 {
            if p % 2 == l % 2 {
                buffer.write(l, p, COLOR_01);
            } else if (p / 16) % 2 == (l / 16) % 2 {
                buffer.write(l, p, COLOR_0B);
            } else {
                buffer.write(l, p, COLOR_16);
            }
        }
    }
    nes.ppu().render_buffer.assert_eq(&buffer);
});

rom_test!(ppu_vertical_write, "ppu_vertical_write.nes", |nes| {
    assert_eq!(nes.last_instruction(), "0x8040 HLT :2 []");

    assert_eq!(nes.mem().peek_ppu(0x2000), Ok(1));
    assert_eq!(nes.mem().peek_ppu(0x2020), Ok(1));
    assert_eq!(nes.mem().peek_ppu(0x2400), Ok(2));
    assert_eq!(nes.mem().peek_ppu(0x2401), Ok(2));
});

rom_test!(ppu_palette_shared, "ppu_palette_shared.nes", |nes| {
    assert_eq!(nes.last_instruction(), "0x8078 HLT :2 []");

    
});

// Sets up an image, and scrolls a specific number of pixels over
rom_test!(ppu_scrolling, "ppu_fine_x_scrolling.nes", timeout = 86964*4, |nes| {
    assert_eq!(nes.image().read(0, 0), Color { r: 0xFF, g: 0xFE, b: 0xFF });
});
