// Fragments - connection_popover.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 glib::{clone, subclass};
use gtk::prelude::*;
use gtk::subclass::prelude::*;
use gtk::{glib, CompositeTemplate};

use crate::app::FrgApplication;
use crate::backend::{FrgConnection, FrgConnectionManager};
use crate::ui::FrgConnectionRow;

mod imp {
    use super::*;

    #[derive(Debug, CompositeTemplate, Default)]
    #[template(resource = "/de/haeckerfelix/Fragments/gtk/connection_popover.ui")]
    pub struct FrgConnectionPopover {
        #[template_child]
        listbox: TemplateChild<gtk::ListBox>,
    }

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

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

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

    impl ObjectImpl for FrgConnectionPopover {
        fn constructed(&self) {
            self.parent_constructed();
            let cm = FrgConnectionManager::default();

            self.listbox
                .connect_row_activated(clone!(@weak self as this => move |_, row|{
                    let row = row.downcast_ref::<FrgConnectionRow>().unwrap();
                    let app = FrgApplication::default();

                    app.activate_action("set-connection", Some(&row.connection().uuid().to_variant()));
                    this.obj().popdown();
                }));

            self.listbox
                .bind_model(Some(&cm.connections()), |connection| {
                    FrgConnectionRow::new(connection.downcast_ref::<FrgConnection>().unwrap())
                        .upcast()
                });

            cm.connect_current_connection_notify(clone!(@weak self as this => move |_|{
                this.update_ui();
            }));

            cm.client()
                .connect_is_busy_notify(clone!(@weak self as this => move |client|{
                    // Don't allow changing the active connection
                    // when the client is still busy establishing a connection
                    this.obj().set_sensitive(!client.is_busy());
                }));

            cm.connections()
                .connect_items_changed(clone!(@weak self as this => move |_,_,_,_|{
                    this.update_ui();
                }));

            self.update_ui();
        }
    }

    impl WidgetImpl for FrgConnectionPopover {}

    impl PopoverImpl for FrgConnectionPopover {}

    impl FrgConnectionPopover {
        fn update_ui(&self) {
            let cm = FrgConnectionManager::default();

            let mut i = 0;
            let current = cm.current_connection();

            while let Some(row) = self.listbox.row_at_index(i) {
                let row = row.downcast::<FrgConnectionRow>().unwrap();
                row.set_selected(row.connection() == current);
                i += 1;
            }
        }
    }
}

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