//! wlr-input-inhibitor-unstable-v1 protocol implementation.
//!
//! Allows a privileged client to inhibit input events to all other clients,
//! typically used by lockscreens to prevent input from reaching applications.

use smithay::reexports::wayland_protocols_wlr::input_inhibitor::v1::server::{
    zwlr_input_inhibit_manager_v1::{self, ZwlrInputInhibitManagerV1},
    zwlr_input_inhibitor_v1::ZwlrInputInhibitorV1,
};
use smithay::reexports::wayland_server::{
    Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New,
};
use tracing::debug;

const MANAGER_VERSION: u32 = 1;

pub struct InputInhibitorState;

impl InputInhibitorState {
    pub fn new<D>(display: &DisplayHandle) -> Self
    where
        D: GlobalDispatch<ZwlrInputInhibitManagerV1, ()>
            + Dispatch<ZwlrInputInhibitManagerV1, ()>
            + Dispatch<ZwlrInputInhibitorV1, ()>
            + 'static,
    {
        display.create_global::<D, ZwlrInputInhibitManagerV1, _>(MANAGER_VERSION, ());
        Self
    }
}

impl<D> GlobalDispatch<ZwlrInputInhibitManagerV1, (), D> for InputInhibitorState
where
    D: GlobalDispatch<ZwlrInputInhibitManagerV1, ()>
        + Dispatch<ZwlrInputInhibitManagerV1, ()>
        + Dispatch<ZwlrInputInhibitorV1, ()>
        + 'static,
{
    fn bind(
        _state: &mut D,
        _display: &DisplayHandle,
        _client: &Client,
        resource: New<ZwlrInputInhibitManagerV1>,
        _data: &(),
        data_init: &mut DataInit<'_, D>,
    ) {
        data_init.init(resource, ());
        debug!("wlr-input-inhibit-manager bound");
    }
}

impl<D> Dispatch<ZwlrInputInhibitManagerV1, (), D> for InputInhibitorState
where
    D: Dispatch<ZwlrInputInhibitManagerV1, ()>
        + Dispatch<ZwlrInputInhibitorV1, ()>
        + 'static,
{
    fn request(
        _state: &mut D,
        _client: &Client,
        _resource: &ZwlrInputInhibitManagerV1,
        request: zwlr_input_inhibit_manager_v1::Request,
        _data: &(),
        _display: &DisplayHandle,
        data_init: &mut DataInit<'_, D>,
    ) {
        match request {
            zwlr_input_inhibit_manager_v1::Request::GetInhibitor { id } => {
                data_init.init(id, ());
                debug!("Input inhibitor created");
            }
            _ => {}
        }
    }
}

impl<D> Dispatch<ZwlrInputInhibitorV1, (), D> for InputInhibitorState
where
    D: Dispatch<ZwlrInputInhibitorV1, ()> + 'static,
{
    fn request(
        _state: &mut D,
        _client: &Client,
        _resource: &ZwlrInputInhibitorV1,
        _request: <ZwlrInputInhibitorV1 as smithay::reexports::wayland_server::Resource>::Request,
        _data: &(),
        _display: &DisplayHandle,
        _data_init: &mut DataInit<'_, D>,
    ) {
        // Only request is Destroy, handled by wayland-server
    }
}

#[macro_export]
macro_rules! delegate_input_inhibitor {
    ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
        smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            smithay::reexports::wayland_protocols_wlr::input_inhibitor::v1::server::zwlr_input_inhibit_manager_v1::ZwlrInputInhibitManagerV1: ()
        ] => $crate::protocols::input_inhibitor::InputInhibitorState);

        smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            smithay::reexports::wayland_protocols_wlr::input_inhibitor::v1::server::zwlr_input_inhibit_manager_v1::ZwlrInputInhibitManagerV1: ()
        ] => $crate::protocols::input_inhibitor::InputInhibitorState);

        smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            smithay::reexports::wayland_protocols_wlr::input_inhibitor::v1::server::zwlr_input_inhibitor_v1::ZwlrInputInhibitorV1: ()
        ] => $crate::protocols::input_inhibitor::InputInhibitorState);
    };
}
