use crate::App;
use crate::themes::NewsflashTheme;
use glib::{Object, Properties, clone, prelude::*, subclass::*};
use gtk4::{Accessible, Buildable, CompositeTemplate, ConstraintTarget, Label, Widget, subclass::prelude::*};
use libadwaita::{Bin, subclass::prelude::*};
use std::cell::{Cell, RefCell};

mod imp {
    use gtk4::prelude::WidgetExt;

    use super::*;

    #[derive(Debug, Default, CompositeTemplate, Properties)]
    #[properties(wrapper_type = super::ThemeTile)]
    #[template(file = "data/resources/ui_templates/settings/theme_tile.blp")]
    pub struct ThemeTile {
        #[template_child]
        pub label: TemplateChild<Label>,

        #[property(get, set = Self::set_selected)]
        pub selected: Cell<bool>,

        #[property(get, set, name = "theme-name", construct_only)]
        pub name: RefCell<String>,

        #[property(get, set, builder(NewsflashTheme::Default))]
        pub theme: Cell<NewsflashTheme>,
    }

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

        fn class_init(klass: &mut Self::Class) {
            klass.bind_template();
            klass.bind_template_callbacks();
            klass.set_css_name("theme-tile");
        }

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

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

            App::default().settings().general().connect_theme_notify(clone!(
                #[weak]
                obj,
                move |settings| {
                    obj.set_selected(obj.theme() == settings.theme());
                }
            ));

            obj.add_css_class(&format!("article-theme-{}", self.name.borrow().to_lowercase()));

            self.parent_constructed();
        }
    }

    impl WidgetImpl for ThemeTile {}

    impl BinImpl for ThemeTile {}

    #[gtk4::template_callbacks]
    impl ThemeTile {
        #[template_callback]
        fn on_gestureclick_released(&self) {
            App::default().settings().general().set_theme(self.theme.get());
        }

        fn set_selected(&self, selected: bool) {
            if selected {
                self.obj().add_css_class("selected");
            } else {
                self.obj().remove_css_class("selected");
            }
            self.selected.set(selected);
        }
    }
}

glib::wrapper! {
    pub struct ThemeTile(ObjectSubclass<imp::ThemeTile>)
        @extends Widget, Bin,
        @implements Accessible, Buildable, ConstraintTarget;
}

impl From<&NewsflashTheme> for ThemeTile {
    fn from(value: &NewsflashTheme) -> Self {
        let is_selected = App::default().settings().general().theme() == *value;
        Object::builder()
            .property("theme", value)
            .property("theme-name", value.to_string())
            .property("selected", is_selected)
            .build()
    }
}
