// SPDX-License-Identifier: GPL-3.0-or-later
use gtk::{
    glib::{self, clone},
    prelude::*,
    subclass::prelude::*,
};

use crate::{model::QRCodeModel, qrcode::QRCode, widgets::QRCodeRow};

mod imp {
    use std::sync::LazyLock;

    use glib::subclass::Signal;

    use super::*;

    #[derive(Default, gtk::CompositeTemplate)]
    #[template(resource = "/com/belmoussaoui/Decoder/ui/history_page.ui")]
    pub struct HistoryPage {
        #[template_child]
        pub stack: TemplateChild<gtk::Stack>,
        #[template_child]
        pub listbox: TemplateChild<gtk::ListBox>,
        #[template_child]
        pub empty_page: TemplateChild<adw::StatusPage>,
    }

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

        fn class_init(klass: &mut Self::Class) {
            klass.set_layout_manager_type::<gtk::BinLayout>();
            klass.set_css_name("history");
            klass.bind_template();
            klass.bind_template_callbacks();
        }

        fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
            obj.init_template();
        }
    }
    impl ObjectImpl for HistoryPage {
        fn signals() -> &'static [Signal] {
            static SIGNALS: LazyLock<Vec<Signal>> = LazyLock::new(|| {
                vec![
                    Signal::builder("exported")
                        .param_types([String::static_type()])
                        .build(),
                ]
            });
            SIGNALS.as_ref()
        }

        fn dispose(&self) {
            self.dispose_template();
        }
    }
    impl WidgetImpl for HistoryPage {}

    #[gtk::template_callbacks]
    impl HistoryPage {
        #[template_callback]
        fn on_row_activated(_listbox: &gtk::ListBox, row: &gtk::ListBoxRow) {
            row.downcast_ref::<QRCodeRow>().unwrap().reveal();
        }
    }
}

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

impl HistoryPage {
    pub fn set_model(&self, model: &QRCodeModel) {
        let imp = self.imp();

        let stack = imp.stack.get();
        model.connect_items_changed(clone!(
            #[weak]
            model,
            #[weak]
            stack,
            move |_, _, _, _| {
                if model.n_items() == 0 {
                    stack.set_visible_child_name("empty");
                } else {
                    stack.set_visible_child_name("content");
                }
            }
        ));

        imp.listbox.bind_model(
            Some(model),
            clone!(
                #[weak]
                model,
                #[weak(rename_to = page)]
                self,
                #[upgrade_or_panic]
                move |item| {
                    let code = item.downcast_ref::<QRCode>().unwrap();

                    let row = QRCodeRow::new(code);
                    row.connect_deleted(clone!(
                        #[weak]
                        model,
                        #[weak]
                        code,
                        move |_| {
                            if let Some(pos) = model.position(&code) {
                                model.remove(pos);
                            }
                        }
                    ));
                    row.connect_exported(clone!(
                        #[weak]
                        page,
                        move |_, content| {
                            page.emit_exported(content);
                        }
                    ));
                    row.upcast()
                }
            ),
        );
    }

    pub fn emit_exported(&self, code: &str) {
        self.emit_by_name::<()>("exported", &[&code]);
    }
}
