use bitfield::bitfield;
bitfield! {
    #[derive(PartialEq, Eq, Hash, Clone, Copy)]
    pub struct ControllerState(u8);
    impl Debug;
    pub a, set_a: 0;
    pub b, set_b: 1;
    pub select, set_select: 2;
    pub start, set_start: 3;
    pub up, set_up: 4;
    pub down, set_down: 5;
    pub left, set_left: 6;
    pub right, set_right: 7;
}

#[derive(Debug, Clone, Copy)]
struct ControllerShiftReg {
    state: ControllerState,
    shift: u8,
}

impl ControllerShiftReg {
    fn new() -> Self {
        Self {
            state: ControllerState(0),
            shift: 0,
        }
    }

    fn read(&mut self) -> u8 {
        let val = self.shift & 1;
        // Reads after the first 8 are always 1
        self.shift = (self.shift >> 1) | 0x80;
        val
    }

    fn load(&mut self) {
        self.shift = self.state.0;
    }
}

#[derive(Debug, Clone)]
pub struct Controllers {
    strobe: bool,
    primary: ControllerShiftReg,
    secondary: ControllerShiftReg,
}

impl Controllers {
    pub fn init() -> Self {
        Self {
            strobe: false,
            primary: ControllerShiftReg::new(),
            secondary: ControllerShiftReg::new(),
        }
    }

    pub fn reset(&mut self) {
        *self = Self::init();
    }

    pub fn read_joy1(&mut self) -> u8 {
        if self.strobe {
            self.primary.load();
        }
        // TODO: Technically some kind of open-bus for all but the lowest 3 bits
        self.primary.read() | 0x40
    }

    pub fn read_joy2(&mut self) -> u8 {
        if self.strobe {
            self.secondary.load();
        }
        self.secondary.read() | 0x40
    }

    pub fn write_joy_strobe(&mut self, val: u8) {
        if val & 1 == 0 {
            if self.strobe {
                self.primary.load();
                self.secondary.load();
            }
            self.strobe = false;
        } else {
            self.strobe = true;
            self.primary.load();
            self.secondary.load();
        }
    }

    pub fn controller_1(&mut self) -> &mut ControllerState {
        &mut self.primary.state
    }

    pub fn controller_2(&mut self) -> &mut ControllerState {
        &mut self.secondary.state
    }
}
