use crate::prelude::*;

gtk::glib::wrapper! {
    /// A grid of multiple emojis displayed in the message menu for reacting to them.
    pub struct EmojiPicker(ObjectSubclass<imp::EmojiPicker>)
        @extends gtk::Box, gtk::Widget,
        @implements gtk::gio::ActionGroup, gtk::gio::ActionMap, gtk::Accessible, gtk::Buildable,
            gtk::ConstraintTarget;
}

impl EmojiPicker {
    pub fn new() -> Self {
        log::trace!("Initializing `EmojiPicker`");
        Object::builder::<Self>().build()
    }
}

impl Default for EmojiPicker {
    fn default() -> Self {
        Self::new()
    }
}

pub mod imp {
    use crate::prelude::*;
    use glib::subclass::{InitializingObject, Signal};
    use gtk::CompositeTemplate;

    #[derive(CompositeTemplate, Default)]
    #[template(resource = "/ui/components/emoji_picker.ui")]
    pub struct EmojiPicker {}

    #[glib::object_subclass]
    impl ObjectSubclass for EmojiPicker {
        const NAME: &'static str = "FlEmojiPicker";
        type Type = super::EmojiPicker;
        type ParentType = gtk::Box;

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

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

    #[gtk::template_callbacks]
    impl EmojiPicker {
        #[template_callback]
        pub(super) fn btn_emoji_clicked(&self) {
            crate::trace!("Opening emoji dropdown",);
            let obj = self.obj();
            obj.emit_by_name::<()>("btn-emoji-clicked", &[]);
        }

        pub(super) fn reacted(&self, emoji: String) {
            let obj = self.obj();
            obj.emit_by_name::<()>("reacted", &[&emoji]);
        }

        #[template_callback]
        pub(super) fn button_react(&self, button: gtk::Button) {
            let emoji = button.label();
            if let Some(emoji) = emoji {
                self.reacted(emoji.to_string());
            }
        }
    }

    impl ObjectImpl for EmojiPicker {
        fn constructed(&self) {
            self.parent_constructed();
        }

        fn signals() -> &'static [Signal] {
            static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
                vec![
                    Signal::builder("reacted")
                        .param_types([String::static_type()])
                        .build(),
                    Signal::builder("btn-emoji-clicked").build(),
                ]
            });
            SIGNALS.as_ref()
        }
    }

    impl WidgetImpl for EmojiPicker {}
    impl BoxImpl for EmojiPicker {}
}
