use ashpd::desktop::{
    screencast::{CursorMode, Screencast, SourceType},
    PersistMode,
};
use godot::classes::{INode, Node};
use godot::prelude::*;
use godot_tokio::AsyncRuntime;

#[derive(GodotClass)]
#[class(base=Node)]
struct XdgPortals {
    base: Base<Node>,
    last_request_completed: bool,
}

#[godot_api]
impl INode for XdgPortals {
    fn init(base: Base<Node>) -> Self {
        Self {
            base,
            last_request_completed: true,
        }
    }
}

#[godot_api]
impl XdgPortals {
    #[signal]
    fn screencast_sucess(pipewire_node_id: u32);

    #[func]
    fn was_last_request_completed(&self) -> bool {
        self.last_request_completed
    }

    #[func]
    fn request_screencast(&mut self) {
        godot_print!("Starting request");
        self.last_request_completed = false;
        AsyncRuntime::block_on(async {
            godot_print!("Starting request async");
            let proxy = Screencast::new().await.expect("Screencast proxy failed");
            let session = match proxy.create_session().await {
                Ok(x) => x,
                Err(err) => {
                    godot_warn!("Failed to create session: {}", err);
                    return;
                }
            };
            godot_print!("Got proxy");
            match proxy
                .select_sources(
                    &session,
                    CursorMode::Metadata,
                    SourceType::Monitor | SourceType::Window,
                    true,
                    None,
                    PersistMode::DoNot,
                )
                .await
            {
                Ok(_) => {}
                Err(err) => {
                    godot_warn!("Err while selecting source: {}", err);
                    return;
                }
            }
            godot_print!("Selected source");

            let starter = match proxy.start(&session, None).await {
                Ok(x) => x,
                Err(err) => {
                    godot_warn!("Error while starting: {}", err);
                    return;
                }
            };
            let result = match starter.response() {
                Ok(x) => x,
                Err(err) => {
                    godot_warn!("Err for response: {}", err);
                    return;
                }
            };
            godot_print!("Got response");
            result.streams().iter().for_each(|stream| {
                godot_print!("node id: {}", stream.pipe_wire_node_id());
                godot_print!("size: {:?}", stream.size());
                godot_print!("position: {:?}", stream.position());
                self.base_mut().emit_signal(
                    "screencast_sucess",
                    &[stream.pipe_wire_node_id().to_variant()],
                );
                self.last_request_completed = true;
            });
        });
    }
}
