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

use crate::{config, widgets::Window};

mod imp {
    use super::*;

    #[derive(Debug, Default)]
    pub struct Application;

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

    impl ObjectImpl for Application {}
    impl ApplicationImpl for Application {
        fn startup(&self) {
            let app = self.obj();
            self.parent_startup();

            aperture::init(config::APP_ID);

            gtk::Window::set_default_icon_name(config::APP_ID);

            let actions = [
                gio::ActionEntryBuilder::new("quit")
                    .activate(|app: &super::Application, _, _| app.quit())
                    .build(),
                gio::ActionEntryBuilder::new("about")
                    .activate(|app: &super::Application, _, _| {
                        let window = app.active_window().unwrap();
                        let about_dialog = adw::AboutDialog::builder()
                            .version(config::VERSION)
                            .website("https://gitlab.gnome.org/World/decoder/")
                            .issue_url("https://gitlab.gnome.org/World/decoder/-/issues/new")
                            .developer_name("Bilal Elmoussaoui")
                            .developers(vec!["Bilal Elmoussaoui", "Maximiliano Sandoval"])
                            .designers(vec!["Tobias Bernard"])
                            .translator_credits(gettext("translator-credits"))
                            .application_icon(config::APP_ID)
                            .application_name(gettext("Decoder"))
                            .license_type(gtk::License::Gpl30)
                            .build();

                        about_dialog.present(Some(&window));
                    })
                    .build(),
            ];

            app.add_action_entries(actions);

            app.set_accels_for_action("window.close", &["<Control>w"]);
            app.set_accels_for_action("app.quit", &["<Control>q"]);
            app.set_accels_for_action("win.scan-qr", &["<Control>s"]);
        }

        fn shutdown(&self) {
            async_io::block_on(crate::database::close_pool());

            self.parent_shutdown();
        }

        fn activate(&self) {
            let app = self.obj();

            if let Some(window) = app.active_window() {
                window.present();
                return;
            }
            let window = Window::new(&app);
            window.present();
        }
    }

    impl GtkApplicationImpl for Application {}
    impl AdwApplicationImpl for Application {}
}

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

impl Application {
    pub fn run() -> glib::ExitCode {
        tracing::info!("Decoder ({})", config::APP_ID);
        tracing::info!("Version: {} ({})", config::VERSION, config::PROFILE);
        tracing::info!("Datadir: {}", config::PKGDATADIR);

        let app = glib::Object::builder::<Application>()
            .property("application-id", config::APP_ID)
            .property("resource-base-path", "/com/belmoussaoui/Decoder/")
            .build();

        app.run()
    }
}
