// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only

//! # DBus interface proxy for: `org.freedesktop.UPower.KbdBacklight`
//!
//! This code was generated by `zbus-xmlgen` `2.0.1` from DBus introspection data.
//! Source: `Interface '/org/freedesktop/UPower/KbdBacklight' from service 'org.freedesktop.UPower' on system bus`.
use cctk::{sctk::reexports::calloop, toplevel_info::ToplevelInfo};
use cosmic::{
    cctk::{
        self,
        wayland_protocols::ext::foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1,
    },
    iced::core::Bytes,
    iced::{self, Subscription},
    iced::{futures, stream},
};
use futures::SinkExt;
use image::EncodableLayout;
use std::fmt::Debug;

use crate::wayland_handler::wayland_handler;

pub fn wayland_subscription() -> iced::Subscription<WaylandUpdate> {
    Subscription::run_with(std::any::TypeId::of::<WaylandUpdate>(), |_| {
        stream::channel(
            1,
            move |mut output: futures::channel::mpsc::Sender<WaylandUpdate>| async move {
                let (calloop_tx, calloop_rx) = calloop::channel::channel();
                let runtime = tokio::runtime::Handle::current();

                let _ = std::thread::spawn(move || {
                    runtime.block_on(async move {
                        _ = output.send(WaylandUpdate::Init(calloop_tx)).await;
                        wayland_handler(output.clone(), calloop_rx);
                        tracing::error!("Wayland handler thread died");
                        _ = output.send(WaylandUpdate::Finished).await;
                    });
                });

                futures::future::pending().await
            },
        )
    })
}

#[derive(Clone, Debug)]
pub enum WaylandUpdate {
    Init(calloop::channel::Sender<WaylandRequest>),
    Finished,
    Toplevel(ToplevelUpdate),
    Image(ExtForeignToplevelHandleV1, WaylandImage),
}

#[derive(Debug, Clone)]
pub struct WaylandImage {
    pub img: Bytes,
    pub width: u32,
    pub height: u32,
}

impl WaylandImage {
    pub fn new(img: image::RgbaImage) -> Self {
        Self {
            img: Bytes::copy_from_slice(img.as_bytes()),
            width: img.width(),
            height: img.height(),
        }
    }
}

impl AsRef<[u8]> for WaylandImage {
    fn as_ref(&self) -> &[u8] {
        self.img.as_bytes()
    }
}

#[derive(Clone, Debug)]
pub enum ToplevelUpdate {
    Add(ToplevelInfo),
    Update(ToplevelInfo),
    Remove(ExtForeignToplevelHandleV1),
}

#[derive(Clone, Debug)]
pub enum WaylandRequest {
    Toplevel(ToplevelRequest),
}

#[derive(Debug, Clone)]
pub enum ToplevelRequest {
    Activate(ExtForeignToplevelHandleV1),
}
