// Fragments - torrent_group.rs
// Copyright (C) 2022-2023  Felix Häcker <haeckerfelix@gnome.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

use std::cell::RefCell;

use adw::subclass::prelude::*;
use glib::subclass;
use gtk::prelude::*;
use gtk::{glib, CompositeTemplate};
use transmission_gobject::TrTorrent;

use crate::ui::FrgTorrentRow;

mod imp {
    use super::*;

    #[derive(Default, Debug, CompositeTemplate)]
    #[template(resource = "/de/haeckerfelix/Fragments/gtk/torrent_group.ui")]
    pub struct FrgTorrentGroup {
        #[template_child]
        pub listbox_box: TemplateChild<gtk::Box>,
        pub models: RefCell<Vec<gtk::SortListModel>>,
    }

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

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

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

    impl ObjectImpl for FrgTorrentGroup {}

    impl WidgetImpl for FrgTorrentGroup {}

    impl PreferencesGroupImpl for FrgTorrentGroup {}
}

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

impl FrgTorrentGroup {
    pub fn add_model(&self, model: gtk::SortListModel) {
        let imp = self.imp();

        let listbox = gtk::ListBox::new();
        listbox.add_css_class("content");
        listbox.set_selection_mode(gtk::SelectionMode::None);
        imp.listbox_box.append(&listbox);

        listbox.bind_model(Some(&model), |object| {
            let torrent = object.downcast_ref::<TrTorrent>().unwrap();
            FrgTorrentRow::new(torrent).upcast::<gtk::Widget>()
        });

        listbox.connect_row_activated(move |_, row| {
            row.activate_action("torrent.show-dialog", None).unwrap();
        });

        model.connect_items_changed(
            glib::clone!(@weak self as this, @weak listbox => move |_, _, _, _| {
                let imp = this.imp();

                // Hide this group if all models are empty
                let mut is_empty = true;
                for m in &*imp.models.borrow() {
                    if m.n_items() != 0 {
                        is_empty = false;
                    }
                }
                this.set_visible(!is_empty);

                // Hide empty listboxes
                let mut child = imp.listbox_box.first_child ();
                while let Some(widget) = child {
                    let listbox = widget.downcast_ref::<gtk::ListBox>().unwrap();
                    listbox.set_visible(listbox.row_at_index(0).is_some());
                    child = listbox.next_sibling();
                }
            }),
        );

        imp.models.borrow_mut().insert(0, model);
    }
}
