use adw::prelude::WidgetExt;
use adw::subclass::prelude::*;
use gtk::CompositeTemplate;
use gtk::{gio, glib};

use crate::data::{KrCollection, KrFlatpak};
use crate::utils::error::ToastWindow;
use crate::widgets::pages::*;

mod imp {
    use super::*;

    #[derive(Debug, Default, CompositeTemplate)]
    #[template(file = "main_window.ui")]
    pub struct KrMainWindow {
        #[template_child]
        pub navigation_view: TemplateChild<adw::NavigationView>,
        #[template_child]
        pub toast_overlay: TemplateChild<adw::ToastOverlay>,
        #[template_child]
        pub overview_page: TemplateChild<KrOverviewPage>,
    }

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

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

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

    impl ObjectImpl for KrMainWindow {
        fn constructed(&self) {
            self.parent_constructed();
            let obj = self.obj();

            obj.connect_realize(|obj| {
                // TODO: this should be host data home
                let icon_theme =
                    gtk::IconTheme::for_display(&gtk::prelude::WidgetExt::display(obj));
                icon_theme.add_search_path(
                    glib::home_dir().join(".local/share/flatpak/exports/share/icons"),
                );
                icon_theme
                    .add_search_path(std::path::Path::new("/var/lib/flatpak/exports/share/icons"));
            });
        }
    }
    impl WidgetImpl for KrMainWindow {}

    impl WindowImpl for KrMainWindow {}

    impl ApplicationWindowImpl for KrMainWindow {}

    impl AdwApplicationWindowImpl for KrMainWindow {}
}

glib::wrapper! {
    pub struct KrMainWindow(ObjectSubclass<imp::KrMainWindow>)
        @extends gtk::Widget, gtk::Window, gtk::ApplicationWindow, adw::ApplicationWindow,
        @implements gio::ActionMap, gio::ActionGroup, gtk::Root;
}

impl KrMainWindow {
    pub fn new() -> Self {
        glib::Object::new()
    }

    pub fn show_overview_page(&self) {
        self.imp().navigation_view.pop_to_tag("overview");
    }

    pub fn overview_page(&self) -> KrOverviewPage {
        self.imp().overview_page.clone()
    }

    pub fn show_collection_items(&self, collection: &KrCollection) {
        let page = KrCollectionItemsPage::new(collection);
        self.imp().navigation_view.push(&page);
    }

    pub fn show_flatpak_items(&self, flatpak: &KrFlatpak) {
        let page = KrFlatpakItemsPage::new(flatpak);
        self.imp().navigation_view.push(&page);
    }
}

impl ToastWindow for KrMainWindow {
    fn toast_overlay(&self) -> adw::ToastOverlay {
        self.imp().toast_overlay.clone()
    }
}
