use std::fmt::Display;

use adw::prelude::*;
use gettextrs::gettext;

use crate::app;

pub trait ToastWindow: IsA<gtk::Widget> {
    fn toast_overlay(&self) -> adw::ToastOverlay;
}

pub trait DisplayError<E> {
    fn handle_error(&self, title: impl AsRef<str>);
    fn handle_error_in(&self, title: impl AsRef<str>, toast_overlay: &impl ToastWindow);
}

impl<E: Display, T> DisplayError<E> for Result<T, E> {
    fn handle_error(&self, title: impl AsRef<str>) {
        self.handle_error_in(title, &app().window());
    }

    fn handle_error_in(&self, title: impl AsRef<str>, widget: &impl ToastWindow) {
        if let Err(err) = self {
            eprintln!("{}: {err}", title.as_ref());

            let toast = adw::Toast::builder()
                .title(title.as_ref())
                .button_label(gettext("Show Details"))
                .build();

            let heading = title.as_ref().to_string();
            let body = err.to_string();

            let transient_for = widget.clone();

            toast.connect_local("button-clicked", false, move |_| {
                let msg = adw::AlertDialog::builder()
                    .heading(&heading)
                    .body(&body)
                    .build();

                msg.add_response("close", "Close");

                msg.present(&transient_for);

                None
            });

            widget.toast_overlay().add_toast(toast);
        }
    }
}
