/*
  +---+---+---+---+---+---+
  | 0 | 1 | 2 | 3 | 4 | 5 |
  +---+---+---+---+---+---+
  | 6 | 7 | 8 | 9 | A | B |
  +---+---+---+---+---+---+
  | C | D | E | F | AD| DA|
  +---+---+---+---+---+---+
  | + | PC| ST| RS|   |   |
  +---+---+---+---+---+---+
 */

pub struct Kim1Keypad {
    keys: [bool; 23],
    stepping: bool
}

impl Kim1Keypad {
    pub fn dump(&self) {
        println!("Dumping state of keypad");
    }
}

impl Kim1Keypad {
    fn keyid(from: u8) -> usize{
        (from % 23) as usize
    }
    pub fn new() -> Self {
        Kim1Keypad {
            keys: [false; 23],
            stepping: false
        }
    }

    pub fn toggle_stepping(&mut self) {
        self.stepping = !self.stepping;;
    }

    pub fn set_stepping(&mut self, new_state: bool) {
        self.stepping = new_state
    }

    pub fn press_key(&mut self, key_to_press: u8) {
        self.keys[Self::keyid(key_to_press)] = true;
    }

    pub fn release_key(&mut self, key_to_release: u8) {
        self.keys[Self::keyid(key_to_release)] = false;
    }

    pub fn is_pressed(&self, key: u8) -> bool {
        self.keys[Self::keyid(key)]
    }
}

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

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

    #[test]
    fn keys_are_pressed() {
        let mut kb = Kim1Keypad::new();

        for index in 0..23 {
            assert!(!kb.is_pressed(index));
            kb.press_key(index);
            assert!(kb.is_pressed(index));

            kb.release_key(index);
            assert!(!kb.is_pressed(index));
        }
    }

    #[test]
    fn stepping_changes() {
        let mut kb = Kim1Keypad::new();

        kb.set_stepping(false);

        assert!(!kb.stepping);

        kb.toggle_stepping();

        assert!(kb.stepping);

        kb.toggle_stepping();
        kb.toggle_stepping();
        kb.toggle_stepping();
        kb.toggle_stepping();
        kb.toggle_stepping();

        assert!(!kb.stepping);
    }

    #[test]
    fn out_of_range() {
        let mut kb = Kim1Keypad::new();

        kb.press_key(24);
        assert!(kb.is_pressed(1));
    }
}
