use std::cell::OnceCell;

use adw::prelude::*;
use adw::subclass::prelude::*;
use gettextrs::ngettext;
use glib::Properties;
use gtk::glib;
use gtk::CompositeTemplate;

use crate::app;
use crate::data::KrFlatpak;

mod imp {
    use super::*;

    #[derive(Debug, Default, CompositeTemplate, Properties)]
    #[properties(wrapper_type = super::KrFlatpakRow)]
    #[template(file = "flatpak_row.ui")]
    pub struct KrFlatpakRow {
        #[template_child]
        pub icon: TemplateChild<gtk::Image>,
        #[property(get, set, construct_only)]
        pub flatpak: OnceCell<KrFlatpak>,
    }

    #[glib::object_subclass]
    impl ObjectSubclass for KrFlatpakRow {
        const NAME: &'static str = "KrFlatpakRow";
        type Type = super::KrFlatpakRow;
        type ParentType = adw::ActionRow;

        fn class_init(klass: &mut Self::Class) {
            klass.bind_template();
            klass.bind_template_callbacks();
        }

        fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
            obj.init_template();
        }
    }

    #[glib::derived_properties]
    impl ObjectImpl for KrFlatpakRow {
        fn constructed(&self) {
            self.parent_constructed();
            let obj = self.obj();
            let flatpak = obj.flatpak();

            flatpak
                .bind_property("icon-name", &*self.icon, "icon-name")
                .sync_create()
                .build();

            flatpak
                .bind_property("title", &*obj, "title")
                .sync_create()
                .build();

            flatpak
                .bind_property("item-count", &*obj, "subtitle")
                .transform_to(|_, n: u32| Some(ngettext!("{} key", "{} keys", n, n.to_string())))
                .sync_create()
                .build();
        }
    }

    impl WidgetImpl for KrFlatpakRow {}

    impl ListBoxRowImpl for KrFlatpakRow {}

    impl PreferencesRowImpl for KrFlatpakRow {}

    impl ActionRowImpl for KrFlatpakRow {}

    #[gtk::template_callbacks]
    impl KrFlatpakRow {
        #[template_callback]
        fn on_activated(&self) {
            app().window().show_flatpak_items(&self.obj().flatpak())
        }
    }
}

glib::wrapper! {
    pub struct KrFlatpakRow(ObjectSubclass<imp::KrFlatpakRow>)
        @extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow,
        @implements gtk::Actionable;
}

impl KrFlatpakRow {
    pub fn new(flatpak: &KrFlatpak) -> Self {
        glib::Object::builder().property("flatpak", flatpak).build()
    }
}
