use std::cell::OnceCell;

use adw::prelude::*;
use adw::subclass::prelude::*;
use gettextrs::gettext;
use glib::{clone, Properties};
use gtk::{glib, CompositeTemplate};

use crate::app;
use crate::data::{KrCollection, KrCollectionKind};

mod imp {
    use super::*;

    #[derive(Debug, Default, CompositeTemplate, Properties)]
    #[properties(wrapper_type = super::KrCollectionRow)]
    #[template(file = "collection_row.ui")]
    pub struct KrCollectionRow {
        #[template_child]
        kind_image: TemplateChild<gtk::Image>,
        #[template_child]
        lock_image: TemplateChild<gtk::Image>,
        #[property(get, set, construct_only)]
        collection: OnceCell<KrCollection>,
    }

    #[glib::object_subclass]
    impl ObjectSubclass for KrCollectionRow {
        const NAME: &'static str = "KrCollectionRow";
        type Type = super::KrCollectionRow;
        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 KrCollectionRow {
        fn constructed(&self) {
            self.parent_constructed();
            let obj = self.obj();
            let collection = obj.collection();

            let (icon_name, tooltip) = match collection.kind() {
                KrCollectionKind::Login => {
                    ("avatar-default-symbolic", gettext("System Login Keyring"))
                }
                KrCollectionKind::User => ("dialog-password-symbolic", gettext("User Keyring")),
                KrCollectionKind::Session => (
                    "system-log-out-symbolic",
                    gettext("Temporary Session Keyring"),
                ),
            };
            self.kind_image.set_icon_name(Some(icon_name));
            self.obj().set_tooltip_text(Some(&tooltip));

            collection.regular_items().connect_items_changed(
                clone!(@weak self as this => move |_, _, _, _| this.update_subtitle()),
            );

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

            collection
                .bind_property("is-locked", &self.lock_image.get(), "visible")
                .sync_create()
                .build();

            self.update_subtitle();
        }
    }

    impl WidgetImpl for KrCollectionRow {}

    impl ListBoxRowImpl for KrCollectionRow {}

    impl PreferencesRowImpl for KrCollectionRow {}

    impl ActionRowImpl for KrCollectionRow {}

    #[gtk::template_callbacks]
    impl KrCollectionRow {
        #[template_callback]
        fn on_activated(&self) {
            app()
                .window()
                .show_collection_items(&self.obj().collection());
        }

        fn update_subtitle(&self) {
            let count = self.obj().collection().regular_items().n_items();
            self.obj().set_subtitle(&format!("{} keys", count));
        }
    }
}

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

impl KrCollectionRow {
    pub fn new(collection: &KrCollection) -> Self {
        glib::Object::builder()
            .property("collection", collection)
            .build()
    }
}
