use crate::constants::constants_system::{OFFSET_INT_VECTOR, OFFSET_RESET_VECTOR};
use crate::mos6502cpu::Mos6502Cpu;

enum Mos6502ResetSteps {
    /// there are 6 of these
    DummyRead(u8),
    ReadRstVectorLow,
    ReadRstVectorHigh,
    ReadPcLow,
    ReadPcHigh
}

impl Mos6502Cpu {
    fn reset_step(&mut self, address_bus: u16, data_bus: u8, read: bool) -> (u16, u8, bool) {
        println!("Reset microstep {}", self.microcode_step);
        // we need to do the reset steps
        // reduce the number of remaining microsteps
        self.read_signal = true;
        match self.microcode_step {
            6 => {
                // NMI High byte
            }
            5 => {
                // NMI low byte
            }
            4 => {
                // read first byte of reset vector
                self.address_bus = OFFSET_RESET_VECTOR;
            }
            3 => {
                // at this point data holds the upper byte of our reset vector
                self.reset_vector = (data_bus as u16) << 8;
                println!("Loaded reset vector of 0x{:04x}", self.reset_vector);
                // read secondd byte of reset vector
                self.address_bus = OFFSET_RESET_VECTOR + 1;
            }
            2 => {
                self.reset_vector |= data_bus as u16;
                println!("Loaded reset vector of 0x{:04x}", self.reset_vector);
                // read first byte of interrupt vector
                self.address_bus = OFFSET_INT_VECTOR;
            }
            1 => {
                // read second byte of interrupt vector
                self.address_bus = OFFSET_INT_VECTOR + 1;
            }
            0 => {
                self.int_vector |= data_bus as u16;
                println!("Loaded interrupt vector of 0x{:04x}", self.int_vector);
                self.pc = self.reset_vector;
                println!("Set PC to Reset Vector.  Giddy-up!");
                println!("START HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK");
                // the KIM-1 uses 0x0000 for its initial PC
                self.pc = 0x0000;
                println!("END HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK");
                self.has_reset = true;
            }
            _ => {
            }
        }
        if self.microcode_step > 0 {
            self.microcode_step -= 1;
        }
        (address_bus, data_bus, read)
    }

    /// AccurateTick
    ///
    /// In: address_bus  > Address of data operationm
    ///     data_bus     > Data read or written
    /// State:
    ///     read_bus     > Flag for if cpu is reading or writing the data bus
    ///     cycle_step   > Index for what step of the Decode->Load->Execute cycle we are in
    /// Out: address_bus > address for operation
    ///      data_bus    > data for the operation
    ///      read_bus    > lets rest of the computer know if the CPU is reading from the address
    ///                   provided or if we are writing to the address
    pub fn tick2(&mut self, address_bus: u16, data_bus: u8) -> (u16, u8, bool) {
        println!("STARTING TICK2");
        if !self.has_reset { return self.reset_step(address_bus, data_bus, self.read_signal) }
        // we have completed the reset cycle
        if self.read_signal {
            // we should see new data in the data_bus for us
            let read_data = data_bus;
            println!("READ 0x{read_data:02x} from data bus.");
            self.data_bus = read_data;
        } else {
            // we are writing to the bus.
        }
        (self.address_bus, self.data_bus, self.read_signal)
    }
}
