use log::debug;
use crate::constants::constants_system::SIZE_32KB;
use crate::constants::constants_via6522::{VIA6522_DDRA, VIA6522_DDRB, VIA6522_ORA, VIA6522_ORB};
use crate::periph::mos6522::mos6522::Mos6522;

impl Mos6522 {
    fn max_address(&self) -> u16 {
        self.offset + SIZE_32KB as u16
    }
    /// tick
    ///
    /// data_bus -> 8 bits from the data bus
    /// control  -> 4 bits to identify which register to control
    pub fn tick(&mut self,  address_bus: u16, data_bus: u8,reset: bool, rw: bool) -> (u16, u8) {
        if !(address_bus >= self.offset && address_bus.le(&self.max_address())) {
            return (address_bus, data_bus);
        }

        let local_address = address_bus - self.offset;

        println!("Mos6522 Tick Start -> D:0x{data_bus:02x} / A:0x{address_bus:02x} / {rw} (Actual 0x{local_address:02x} / 0b{local_address:08b})");
        if reset {
            // reset process
            println!("Resetting Mos6522");
            self.data_bus = data_bus;
            self.dda = 0x00;
            self.ddb = 0x00;
            self.porta = 0x00;
            self.portb = 0x00;
            return (self.address_bus, self.data_bus)
        }

        if rw {
            // RW true = CPU is writing
            self.data_bus = data_bus;
            match local_address as u8 {
                VIA6522_DDRA => {
                    println!("Setting DDA to 0x{data_bus:02x}");
                    // setting the Data Direction for Port A
                    self.dda = data_bus;
                },
                VIA6522_ORB => {
                    // writing data to ORB
                    let masked_data = data_bus & self.ddb;
                    println!("Setting ORB to 0x{data_bus:02x} / masked at 0x{masked_data:02x}");
                    self.orb = data_bus;
                    self.portb = masked_data;
                },
                VIA6522_DDRB => {
                    println!("Setting DDB to 0x{data_bus:02x}");
                                 // setting the data direction for port b
                    self.ddb = data_bus;
                },

                VIA6522_ORA => {
                    // writing data to ORA
                    let masked_data = data_bus & self.dda;
                    println!("Setting ORA to 0x{data_bus:02x} / masked at 0x{masked_data:02x}");
                    self.ora = data_bus;
                    self.porta = masked_data;
                },
                _ => {}
            }
        } else {
            // RW false = CPU is reading
            self.data_bus = match local_address as u8 {
                VIA6522_DDRA => {
                    self.dda
                }
                VIA6522_DDRB => {
                    self.ddb
                }
                VIA6522_ORA => {
                    self.porta & self.dda
                }
                VIA6522_ORB => {
                    self.portb & self.ddb
                }
                _ => {
                    debug!("VIA got request for b{:08b} / 0x{:02x}", address_bus, address_bus);
                    // do nothing.  bad address for VIA
                    self.data_bus
                }
            }
        }

        (self.address_bus, self.data_bus)
    }
}