use std::sync::{Arc, Mutex};

use log::{error, info, warn};
use rog_anime::Animations;
use rog_dbus::zbus_anime::AnimeProxy;
use slint::ComponentHandle;

use crate::config::Config;
use crate::ui::show_toast;
use crate::{set_ui_callbacks, set_ui_props_async, AnimePageData, MainWindow};

pub fn setup_anime_page(ui: &MainWindow, _states: Arc<Mutex<Config>>) {
    let handle = ui.as_weak();
    tokio::spawn(async move {
        let Ok(conn) = zbus::Connection::system().await.map_err(|e| warn!("{e:}")) else {
            return;
        };
        let Ok(anime) = AnimeProxy::new(&conn).await.map_err(|e| warn!("{e:}")) else {
            info!("This device may not have an AniMe. If not then the error can be ignored");
            return;
        };

        set_ui_props_async!(handle, anime, AnimePageData, brightness);
        set_ui_props_async!(handle, anime, AnimePageData, builtins_enabled);
        set_ui_props_async!(handle, anime, AnimePageData, enable_display);
        set_ui_props_async!(handle, anime, AnimePageData, off_when_lid_closed);
        set_ui_props_async!(handle, anime, AnimePageData, off_when_suspended);
        set_ui_props_async!(handle, anime, AnimePageData, off_when_unplugged);

        let builtins = anime.builtin_animations().await.unwrap_or_default();
        handle
            .upgrade_in_event_loop(move |handle| {
                {
                    let global = handle.global::<AnimePageData>();
                    global.set_boot_anim(builtins.boot as i32);
                    global.set_awake_anim(builtins.awake as i32);
                    global.set_sleep_anim(builtins.sleep as i32);
                    global.set_shutdown_anim(builtins.shutdown as i32);

                    let handle_copy = handle.as_weak();
                    let anime_copy = anime.clone();
                    global.on_set_builtin_animations(move |boot, awake, sleep, shutdown| {
                        let handle_copy = handle_copy.clone();
                        let anime_copy = anime_copy.clone();
                        tokio::spawn(async move {
                            show_toast(
                                "Anime builtin animations changed".into(),
                                "Failed to set Anime builtin animations".into(),
                                handle_copy,
                                anime_copy
                                    .set_builtin_animations(Animations {
                                        boot: boot.into(),
                                        awake: awake.into(),
                                        sleep: sleep.into(),
                                        shutdown: shutdown.into(),
                                    })
                                    .await,
                            );
                        });
                    });

                    let handle_copy = handle.as_weak();
                    let anime_copy = anime.clone();
                    tokio::spawn(async move {
                        let mut x = anime_copy.receive_builtin_animations_changed().await;
                        use zbus::export::futures_util::StreamExt;
                        while let Some(e) = x.next().await {
                            if let Ok(out) = e.get().await {
                                handle_copy
                                    .upgrade_in_event_loop(move |handle| {
                                        handle
                                            .global::<AnimePageData>()
                                            .set_boot_anim(out.boot.into());
                                        handle
                                            .global::<AnimePageData>()
                                            .set_awake_anim(out.awake.into());
                                        handle
                                            .global::<AnimePageData>()
                                            .set_sleep_anim(out.sleep.into());
                                        handle
                                            .global::<AnimePageData>()
                                            .set_shutdown_anim(out.shutdown.into());
                                    })
                                    .ok();
                            }
                        }
                    });
                }

                set_ui_callbacks!(handle,
                    AnimePageData(.into()),
                    anime.brightness(.into()),
                    "Anime LED brightness successfully set to {}",
                    "Setting Anime LED brightness failed"
                );
                set_ui_callbacks!(
                    handle,
                    AnimePageData(),
                    anime.builtins_enabled(),
                    "Keyboard LED mode successfully set to {}",
                    "Setting keyboard LEDmode failed"
                );
                set_ui_callbacks!(
                    handle,
                    AnimePageData(),
                    anime.enable_display(),
                    "Anime display successfully set to {}",
                    "Setting Anime display failed"
                );
                set_ui_callbacks!(
                    handle,
                    AnimePageData(),
                    anime.off_when_lid_closed(),
                    "Anime off_when_lid_closed successfully set to {}",
                    "Setting Anime off_when_lid_closed failed"
                );
                set_ui_callbacks!(
                    handle,
                    AnimePageData(),
                    anime.off_when_suspended(),
                    "Anime off_when_suspended successfully set to {}",
                    "Setting Anime off_when_suspended failed"
                );
                set_ui_callbacks!(
                    handle,
                    AnimePageData(),
                    anime.off_when_unplugged(),
                    "Anime off_when_unplugged successfully set to {}",
                    "Setting Anime off_when_unplugged failed"
                );
            })
            .map_err(|e| error!("setup_anime_page: upgrade_in_event_loop: {e:?}"))
            .ok();
    });
}
