use crate::constants::constants_system::SIZE_32KB;
use crate::periph::hm62256::Hm62256;

impl Hm62256 {
    fn max_address(&self) -> u16 {
        self.offset + SIZE_32KB as u16
    }

    pub fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool, cs: bool) -> (u16, u8) {
        println!("HM62256RAM TICK START -> 0x{address_bus:04x} 0x{data_bus:02x} {read_mode} {cs}");
        if !(address_bus >= self.offset && address_bus < self.max_address()) {
            return (address_bus, data_bus);
        }

        self.address_bus = address_bus;
        self.data_bus = data_bus;
        let addr = address_bus.wrapping_sub(self.offset) + self.offset;

        // did we want to talk to the chip...
          if !cs {
            return (address_bus, data_bus);
        }

        // ...or are we outside the range?
        if (addr - self.offset) > SIZE_32KB as u16 {
            return (address_bus, data_bus);
        }


        // ok.  lets see what we are dealing with
        self.data_bus = if read_mode {
            let new_value = self.data[addr as usize];
            new_value
        } else {
            // writing to ram
            self.data[addr as usize] = data_bus.into();
            data_bus
        };
        (self.address_bus, self.data_bus)
    }
}

#[cfg(test)]
mod test {
    use super::*;

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

    #[test]
    fn write_to_memory_read_back_works_at_0() {
        let mut ram = Hm62256::default();

        // load the data to ram
        ram.tick(0x0000, 0xab, false, true);
        // read the data back
        let (_, new_data) = ram.tick(0x0000, 0x00, true, true);

        assert_eq!(new_data, 0xab);
    }
}
