use crate::gobject_models::GPluginID;
use glib::{Object, Properties, clone, prelude::*, subclass::*};
use gtk4::{
    Accessible, Actionable, Buildable, CompositeTemplate, ConstraintTarget, ListBoxRow, Svg, Widget,
    subclass::prelude::*,
};
use libadwaita::{ActionRow, PreferencesRow, prelude::*, subclass::prelude::*};
use news_flash::models::{PluginIcon, PluginInfo};
use std::cell::RefCell;

mod imp {
    use super::*;

    #[derive(Default, Debug, CompositeTemplate, Properties)]
    #[properties(wrapper_type = super::ServiceRow)]
    #[template(file = "data/resources/ui_templates/login/service_row.blp")]
    pub struct ServiceRow {
        #[property(get, set, nullable)]
        pub logo: RefCell<Option<Svg>>,

        #[property(get, set, name = "plugin-id")]
        pub plugin_id: RefCell<GPluginID>,
    }

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

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

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

    #[glib::derived_properties]
    impl ObjectImpl for ServiceRow {}

    impl WidgetImpl for ServiceRow {}

    impl ListBoxRowImpl for ServiceRow {}

    impl PreferencesRowImpl for ServiceRow {}

    impl ActionRowImpl for ServiceRow {}
}

glib::wrapper! {
    pub struct ServiceRow(ObjectSubclass<imp::ServiceRow>)
        @extends Widget, ActionRow, PreferencesRow, ListBoxRow,
        @implements Accessible, Actionable, Buildable, ConstraintTarget;
}

impl Default for ServiceRow {
    fn default() -> Self {
        Object::new::<Self>()
    }
}

impl ServiceRow {
    pub fn new(info: PluginInfo) -> Self {
        let row = Self::default();
        glib::spawn_future_local(clone!(
            #[weak]
            row,
            async move {
                row.set_service(info).await;
            }
        ));
        row
    }

    async fn set_service(&self, info: PluginInfo) {
        let plugin_id: GPluginID = info.id.clone().into();
        self.set_plugin_id(plugin_id);
        self.set_title(&info.name);

        if let Some(PluginIcon::Vector(icon)) = info.icon {
            let bytes = glib::Bytes::from_owned(icon.data);
            let svg = Svg::from_bytes(&bytes);
            self.set_logo(Some(svg));
        }
    }
}
