use defmt::{info, warn};
use embedded_midi::{MidiOut, MidiMessage, Channel, Control};
use midi_types::Value7;
use stm32f0xx_hal::gpio::{Input, Floating, gpiob};
use stm32f0xx_hal::prelude::*;

pub struct ButtonHandler {
    pub states: [bool; 12],
}

impl ButtonHandler {
    pub fn new() -> Self {
        Self {
            states: [false; 12],
        }
    }

    pub fn check_and_send_midi(
        &mut self,
        button_index: u8,
        is_pressed: bool,
        midi_tx: &mut MidiOut<stm32f0xx_hal::serial::Tx<stm32f0xx_hal::stm32::USART1>>,
    ) {
        let previous_state = &mut self.states[button_index as usize];
        if is_pressed != *previous_state {
            *previous_state = is_pressed;
            let control = control_from_button(button_index);
            
            if is_pressed {
                info!("Button {} pressed", button_index);
                if midi_tx
                    .write(&MidiMessage::ControlChange(
                        Channel::C1,
                        control,
                        Value7::new(127),
                    ))
                    .is_err()
                {
                    warn!("Failed to send MIDI message");
                }
            } else {
                info!("Button {} released", button_index);
                if midi_tx
                    .write(&MidiMessage::ControlChange(
                        Channel::C1,
                        control,
                        Value7::new(0),
                    ))
                    .is_err()
                {
                    warn!("Failed to send MIDI message");
                }
            }
        }
    }

    pub fn process_buttons(
        &mut self,
        button_1_5: &gpiob::PB13<Input<Floating>>,
        button_6_10: &gpiob::PB11<Input<Floating>>,
        midi_tx: &mut MidiOut<stm32f0xx_hal::serial::Tx<stm32f0xx_hal::stm32::USART1>>,
        i: u8,
    )
    {
        let new_state = button_1_5.is_high().unwrap_or(false);
        self.check_and_send_midi(i, new_state, midi_tx);

        let i = i + 6;
        let new_state = button_6_10.is_high().unwrap_or(false);
        self.check_and_send_midi(i, new_state, midi_tx);
    }
}

fn control_from_button(button: u8) -> Control {
    match button {
        0 => Control::new(20),
        1 => Control::new(21),
        2 => Control::new(22),
        3 => Control::new(23),
        4 => Control::new(24),
        5 => Control::new(31),
        6 => Control::new(25),
        7 => Control::new(26),
        8 => Control::new(27),
        9 => Control::new(28),
        10 => Control::new(29),
        11 => Control::new(30),
        _ => Control::new(0),
    }
}