// SPDX-License-Identifier: GPL-3.0-or-later
use gettextrs::gettext;
use log::{debug, info};

use adw::prelude::*;
use gtk::subclass::prelude::*;
use gtk::{gio, glib};

use crate::config::{APP_ID, APP_NAME, PKGDATADIR, PROFILE, VERSION};
use crate::window::Window;

mod imp {
    use super::*;

    use adw::subclass::prelude::*;

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

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

    impl ObjectImpl for Application {}

    impl ApplicationImpl for Application {
        fn activate(&self) {
            let app = self.obj();
            debug!("GtkApplication<Application>::activate");
            self.parent_activate();

            if let Some(window) = app.active_window() {
                window.present();
                return;
            }

            let window = Window::new(&app);
            window.present();
        }

        fn startup(&self) {
            let app = self.obj();
            debug!("GtkApplication<Application>::startup");
            self.parent_startup();

            // Set icons for shell
            gtk::Window::set_default_icon_name(APP_ID);

            app.setup_gactions();
            app.setup_accels();
        }
    }

    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;
}

#[allow(clippy::new_without_default)]
impl Application {
    pub fn new() -> Self {
        glib::Object::builder()
            .property("application-id", APP_ID)
            .property("resource-base-path", "/org/gnome/design/Lorem/")
            .build()
    }

    fn setup_gactions(&self) {
        let actions = [
            gio::ActionEntryBuilder::new("quit")
                .activate(|app: &Self, _, _| {
                    // This is needed to trigger the delete event and saving the window state
                    if let Some(window) = app.active_window() {
                        window.close();
                    }
                    app.quit();
                })
                .build(),
            gio::ActionEntryBuilder::new("about")
                .activate(|app: &Self, _, _| {
                    app.show_about_dialog();
                })
                .build(),
        ];

        self.add_action_entries(actions);
    }

    // Sets up keyboard shortcuts
    fn setup_accels(&self) {
        self.set_accels_for_action("copy", &["<Control>c"]);
        self.set_accels_for_action("app.quit", &["<Control>q"]);
        self.set_accels_for_action("window.close", &["<Control>w"]);
    }

    fn show_about_dialog(&self) {
        let dialog = adw::AboutDialog::builder()
            .application_icon(APP_ID)
            .application_name(APP_NAME)
            .developer_name("Maximiliano Sandoval")
            .license_type(gtk::License::Gpl30)
            .website("https://gitlab.gnome.org/World/design/lorem/")
            .issue_url("https://gitlab.gnome.org/World/design/lorem/-/issues/new")
            .version(VERSION)
            .translator_credits(gettext("translator-credits"))
            .developers(["Maximiliano Sandoval <msandova@gnome.org>"])
            .designers(["Jorge Toledo", "Tobias Bernard <tbernard@gnome.org>"])
            .build();

        dialog.present(self.active_window().as_ref());
    }

    pub fn run(&self) -> glib::ExitCode {
        info!("Lorem ({APP_ID})");
        info!("Version: {VERSION} ({PROFILE})");
        info!("Datadir: {PKGDATADIR}");

        ApplicationExtManual::run(self)
    }
}
