use std::path::PathBuf;

use gtk::{
    gio,
    glib::{self, clone},
    pango,
    prelude::*,
    subclass::prelude::*,
};

use crate::widgets::{symbolic::icon_name, Window};

mod imp {
    use super::*;

    #[derive(Default, Debug)]
    pub struct RecentItemRow {
        pub(super) label: gtk::Label,
        pub(super) image: gtk::Image,
    }

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

    impl ObjectImpl for RecentItemRow {
        fn constructed(&self) {
            self.parent_constructed();
            let container = gtk::Box::new(gtk::Orientation::Horizontal, 12);
            container.set_height_request(50);
            container.append(&self.image);

            self.label.set_halign(gtk::Align::Start);
            self.label.set_valign(gtk::Align::Center);
            self.label.set_ellipsize(pango::EllipsizeMode::End);
            self.label.add_css_class("recent-item");
            container.append(&self.label);

            self.obj().set_child(Some(&container));
        }
    }
    impl WidgetImpl for RecentItemRow {}
    impl FlowBoxChildImpl for RecentItemRow {}
}

glib::wrapper! {
    pub struct RecentItemRow(ObjectSubclass<imp::RecentItemRow>)
        @extends gtk::Widget, gtk::FlowBoxChild;
}

impl RecentItemRow {
    pub fn new(item: PathBuf) -> Self {
        let widget = glib::Object::new::<Self>();
        widget.set_item(item);
        widget
    }

    fn set_item(&self, item: PathBuf) {
        let imp = self.imp();
        let icon_name = icon_name(&item);

        // If it's a symbolic icon, show a preview of it.
        if item.to_str().unwrap_or("").ends_with("-symbolic.svg") {
            imp.image.set_from_icon_name(Some(&icon_name));
        } else {
            // Otherwise display a gird for icons sets.
            imp.image.set_from_icon_name(Some("view-app-grid-symbolic"));
        }

        imp.label.set_label(&icon_name);
        imp.label.set_tooltip_text(Some(&icon_name));

        let gesture_click = gtk::GestureClick::new();

        gesture_click.connect_pressed(clone!(@weak self as row => move |_, _, _, _| {
            let window = row.root().and_downcast::<Window>().unwrap();
            let file = gio::File::for_path(item.clone());
            let ctx = glib::MainContext::default();
            ctx.spawn_local(async move {
                window.parse_project(file).await;
            });
        }));
        self.add_controller(gesture_click);
    }
}
