use std::os::fd::{AsRawFd, OwnedFd};

use libcolors::{
    event::{EventData, KeyboardKeyEvent},
    message::{ClientMessage, ServerMessage},
};
use uipc::{PeerAddress, Sender};

#[cfg(any(rust_analyzer, unix))]
pub mod unix;
#[cfg(any(rust_analyzer, target_os = "yggdrasil"))]
pub mod yggdrasil;

#[cfg(any(rust_analyzer, unix))]
pub use unix::{Backend, DisplaySurface, Error};
#[cfg(any(rust_analyzer, target_os = "yggdrasil"))]
pub use yggdrasil::{Backend, DisplaySurface, Error};

#[derive(Debug)]
pub struct FromClient {
    pub peer: PeerAddress,
    pub message: ClientMessage,
    pub file: Option<OwnedFd>,
}

pub struct ServerSender {
    sender: Sender<ServerMessage>,
}

#[derive(Debug)]
pub struct Point<T>(pub T, pub T);

pub trait WindowServer {
    fn handle_initial(&mut self, surface: DisplaySurface);
    fn handle_display_resize(&mut self, tx: &mut ServerSender, surface: DisplaySurface);
    fn handle_client_message(
        &mut self,
        surface: DisplaySurface,
        tx: &mut ServerSender,
        message: FromClient,
    );
    fn handle_keyboard_event(
        &mut self,
        surface: DisplaySurface,
        tx: &mut ServerSender,
        event: KeyboardKeyEvent,
    );
}

impl ServerSender {
    pub fn send_event(&self, event: EventData, client_id: &PeerAddress) {
        self.sender
            .send_to(&ServerMessage::Event(event), client_id)
            .ok();
    }

    pub fn send_event_with_file<F: AsRawFd>(
        &self,
        event: EventData,
        file: &F,
        client_id: &PeerAddress,
    ) {
        self.sender
            .send_with_file_to(&ServerMessage::Event(event), file, client_id)
            .ok();
    }
}
