use gtk::{glib, prelude::*, subclass::prelude::*};

use crate::icons::Icon;

mod imp {
    use std::cell::OnceCell;

    use super::*;

    #[derive(Default, Debug, gtk::CompositeTemplate, glib::Properties)]
    #[properties(wrapper_type = super::IconWidget)]
    #[template(string = r#"
    <interface>
        <template class="IconWidget" parent="GtkFlowBoxChild">
            <property name="overflow">hidden</property>
            <property name="height-request">48</property>
            <property name="width-request">48</property>
            <property name="halign">fill</property>
            <property name="valign">fill</property>
            <child>
                <object class="GtkImage" id="image">
                    <property name="pixel-size">32</property>
                    <property name="halign">center</property>
                    <property name="valign">center</property>
                </object>
            </child>
        </template>
    </interface>
    "#)]
    pub struct IconWidget {
        #[template_child]
        pub(super) image: TemplateChild<gtk::Image>,
        #[property(get, set = Self::set_icon, construct_only)]
        pub(super) icon: OnceCell<Icon>,
    }

    #[glib::object_subclass]
    impl ObjectSubclass for IconWidget {
        const NAME: &'static str = "IconWidget";
        type Type = super::IconWidget;
        type ParentType = gtk::FlowBoxChild;
        fn class_init(klass: &mut Self::Class) {
            klass.bind_template();
        }
        fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
            obj.init_template();
        }
    }

    #[glib::derived_properties]
    impl ObjectImpl for IconWidget {}
    impl WidgetImpl for IconWidget {}
    impl FlowBoxChildImpl for IconWidget {}

    impl IconWidget {
        fn set_icon(&self, icon: Icon) {
            self.image
                .set_from_icon_name(Some(&format!("{}-symbolic", icon.name())));
            self.obj().set_tooltip_text(Some(&icon.name()));
            self.icon.set(icon).unwrap();
        }
    }
}

glib::wrapper! {
    pub struct IconWidget(ObjectSubclass<imp::IconWidget>)
        @extends gtk::Widget, gtk::FlowBoxChild;
}

impl IconWidget {
    pub fn new(icon: Icon) -> Self {
        glib::Object::builder().property("icon", icon).build()
    }
}
