pub struct NotificationHandler {
    channel: tokio::sync::broadcast::Sender<JackNotification>,
}

#[derive(Clone, Debug)]
pub enum JackNotification {
    Shutdown {
        status: jack::ClientStatus,
        reason: String,
    },
    PortConnect {
        port_a: String,
        port_b: String,
        connected: bool,
    },
    PortRegistered {},
}

impl NotificationHandler {
    pub fn new() -> Self {
        let (channel, _) = tokio::sync::broadcast::channel(16);
        Self { channel }
    }

    pub fn subscribe(&self) -> tokio::sync::broadcast::Receiver<JackNotification> {
        self.channel.subscribe()
    }
}

impl jack::NotificationHandler for NotificationHandler {
    unsafe fn shutdown(&mut self, status: jack::ClientStatus, reason: &str) {
        let reason = reason.to_string();
        self.channel
            .send(JackNotification::Shutdown { status, reason })
            .expect("Could not send shutdown notification");
    }

    fn ports_connected(
        &mut self,
        client: &jack::Client,
        port_id_a: jack::PortId,
        port_id_b: jack::PortId,
        connect: bool,
    ) {
        // Convert port IDs to port names
        let Some(port_a) = client.port_by_id(port_id_a) else {
            return;
        };
        let Ok(port_a) = port_a.name() else { return };
        let Some(port_b) = client.port_by_id(port_id_b) else {
            return;
        };
        let Ok(port_b) = port_b.name() else { return };

        let notification = JackNotification::PortConnect {
            port_a,
            port_b,
            connected: connect,
        };

        self.channel
            .send(notification)
            .expect("Could not send port connection notification");
    }

    fn port_registration(
        &mut self,
        _client: &jack::Client,
        _port_id: jack::PortId,
        register: bool,
    ) {
        if register {
            let notification = JackNotification::PortRegistered {};
            self.channel
                .send(notification)
                .expect("Could not send port registration notification");
        };
    }

    fn xrun(&mut self, _: &jack::Client) -> jack::Control {
        log::error!("XRUN");
        jack::Control::Continue
    }
}
