// SPDX-License-Identifier: GPL-3.0-or-later

//! Overlay that allows to display in-app toast notifications.

use std::{rc::Rc, time::Duration};

use glib::Cast;
use grx_macros::{gtk_component, props};
use gtk::glib;

use crate::new_gc;

use super::gtk_props::apply;

#[props]
#[derive(Default, Debug)]
pub struct Props {}

#[gtk_component(gtk::Widget)]
#[derive(Debug)]
pub struct ToastOverlay {}

pub fn toast_overlay(mut props: Props) -> Rc<ToastOverlay> {
    let toast_overlay = libadwaita::ToastOverlay::new();
    for c in &props.children {
        toast_overlay.set_child(Some(
            c.clone().inner().downcast_ref::<gtk::Widget>().unwrap(),
        ));
    }
    let widget: gtk::Widget = toast_overlay.upcast();
    let comp = new_gc!(ToastOverlay { widget, props });
    apply(comp.clone());
    comp
}

impl ToastOverlay {
    pub fn show(
        self: &Rc<Self>,
        toast: &Toast,
        on_dismiss: Option<Rc<dyn Fn() + 'static>>,
        _on_timeout: Option<Rc<dyn Fn() + 'static>>,
    ) {
        let to: &libadwaita::ToastOverlay = self.widget.downcast_ref().unwrap();
        let adw_toast = libadwaita::Toast::new(&toast.message);

        if let Some(button) = &toast.button {
            adw_toast.set_button_label(Some(button));
        }

        adw_toast.connect_dismissed(move |_| {
            if let Some(f) = &on_dismiss {
                f()
            }
        });

        // adw_toast.connect_timeout_notify(move |_| {
        //     if let Some(f) = &on_timeout {
        //         f()
        //     }
        // });

        if let Some(timeout) = toast.timeout {
            adw_toast.set_timeout(timeout.as_secs() as u32);
        }

        to.add_toast(adw_toast)
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Toast {
    message: String,
    button: Option<String>,
    timeout: Option<Duration>,
    id: Option<String>,
}
impl Toast {
    pub fn new(message: &str) -> Self {
        Self {
            id: None,
            message: message.into(),
            timeout: None,
            button: None,
        }
    }
    pub fn with_id(mut self, id: Option<String>) -> Self {
        self.id = id;
        self
    }
    pub fn with_button(mut self, button: Option<String>) -> Self {
        self.button = button;
        self
    }
    pub fn with_timeout(mut self, timeout: Option<Duration>) -> Self {
        self.timeout = timeout;
        self
    }

    pub fn id(&self) -> Option<&String> {
        self.id.as_ref()
    }

    pub fn button(&self) -> Option<&String> {
        self.button.as_ref()
    }

    pub fn timeout(&self) -> Option<Duration> {
        self.timeout
    }

    pub fn message(&self) -> &String {
        &self.message
    }
}
