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

use crate::qrcode_kind::{WiFi, WiFiEncryption};

mod imp {
    use std::cell::{Cell, RefCell};

    use super::*;

    #[derive(Debug, Default, gtk::CompositeTemplate, glib::Properties)]
    #[template(resource = "/com/belmoussaoui/Decoder/ui/wifi_page.ui")]
    #[properties(wrapper_type = super::WiFiPage)]
    pub struct WiFiPage {
        #[template_child]
        pub password_entry: TemplateChild<adw::PasswordEntryRow>,
        #[template_child]
        pub network_entry: TemplateChild<adw::EntryRow>,
        #[template_child]
        pub network_visible_row: TemplateChild<adw::SwitchRow>,
        #[template_child]
        pub child: TemplateChild<gtk::Widget>,

        #[property(get, set)]
        content: RefCell<String>,
        #[property(get, set = Self::set_encryption, explicit_notify, default)]
        wifi_encryption: Cell<WiFiEncryption>,
    }

    impl WiFiPage {
        fn set_encryption(&self, encryption: WiFiEncryption) {
            self.wifi_encryption.replace(encryption);
            self.obj().notify_wifi_encryption();

            self.obj().refresh_content();
        }
    }

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

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

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

    #[glib::derived_properties]
    impl ObjectImpl for WiFiPage {
        fn constructed(&self) {
            self.parent_constructed();
            self.obj().refresh_content();
        }

        fn dispose(&self) {
            self.dispose_template();
        }
    }

    impl WidgetImpl for WiFiPage {}

    #[gtk::template_callbacks]
    impl WiFiPage {
        #[template_callback]
        fn on_active_notify(page: &super::WiFiPage) {
            page.refresh_content();
        }

        #[template_callback]
        fn on_changed(page: &super::WiFiPage) {
            page.refresh_content();
        }

        #[template_callback]
        fn wifi_encryption_translatable_string(item: &adw::EnumListItem) -> String {
            WiFiEncryption::from(item.value() as u32).to_translatable_string()
        }
    }
}

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

impl WiFiPage {
    fn refresh_content(&self) {
        let imp = self.imp();

        let network = imp.network_entry.text().to_string();
        let password = imp.password_entry.text().to_string();
        let encryption = self.wifi_encryption();
        let visible = Some(imp.network_visible_row.is_active());

        let content = WiFi {
            network,
            encryption,
            password,
            visible,
        }
        .to_string();

        self.set_content(content);
    }
}
