namespace QuickSetup {
    public const string GETTEXT_DOMAIN = "quick-setup";

    public string tr(string message) {
        return GLib.dgettext(GETTEXT_DOMAIN, message);
    }

    public class QuickSetupApp : Adw.Application {
        public QuickSetupApp() {
            GLib.Intl.setlocale(LocaleCategory.ALL, "");
            GLib.Intl.bindtextdomain(GETTEXT_DOMAIN, "/usr/share/locale");
            GLib.Intl.bind_textdomain_codeset(GETTEXT_DOMAIN, "UTF-8");
            GLib.Intl.textdomain(GETTEXT_DOMAIN);
            Object(
                application_id: "io.stillhq.quicksetup",
                flags: ApplicationFlags.FLAGS_NONE
            );
        }

        protected override void activate() {
            register_bundled_icons();
            run_first_boot_setup();
            pin_forums_to_arcmenu();
            configure_gnome_app_folders();
            ensure_ethernet_connection_on_startup();

            var window = new QuickSetupWindow(this);

            window.maximize();
            window.close_request.connect(() => {
                // Prevent the window from closing unless setup is complete
                return !window.allow_close;
            });
            window.present ();
        }

        private void run_first_boot_setup() {
            string marker = "/var/lib/quick-setup/first-boot-ran";
            if (FileUtils.test(marker, FileTest.EXISTS)) {
                return;
            }

            string helper = "/usr/bin/first-boot";
            if (!FileUtils.test(helper, FileTest.EXISTS)) {
                warning("First-boot setup helper is unavailable: %s", helper);
                return;
            }

            try {
                Process.spawn_async(
                    null,
                    { "/usr/bin/pkexec", helper },
                    null,
                    SpawnFlags.SEARCH_PATH,
                    null,
                    null
                );
            } catch (Error e) {
                warning("Failed to start first-boot setup: %s", e.message);
            }
        }

        // Make our bundled symbolic icons (e.g. firmware-update-symbolic) look
        // up by name through Gtk.IconTheme, so Adw.StatusPage.icon_name works
        // and GTK auto-recolors them to the foreground.
        private void register_bundled_icons() {
            string[] candidate_paths = {
                "/usr/share/quick-setup/icons-symbolic",
                "data/icons-symbolic"
            };

            var display = Gdk.Display.get_default();
            if (display == null) {
                return;
            }

            var theme = Gtk.IconTheme.get_for_display(display);
            string[] existing = theme.get_search_path();

            foreach (string candidate in candidate_paths) {
                if (!FileUtils.test(candidate, FileTest.IS_DIR)) {
                    continue;
                }

                bool already_present = false;
                foreach (string entry in existing) {
                    if (entry == candidate) {
                        already_present = true;
                        break;
                    }
                }

                if (!already_present) {
                    theme.add_search_path(candidate);
                }
            }
        }

        private void ensure_ethernet_connection_on_startup() {
            string stdout_text;
            string stderr_text;
            int wait_status = 0;

            try {
                Process.spawn_sync(
                    null,
                    { "/usr/bin/nmcli", "-t", "-f", "DEVICE,TYPE,STATE", "device", "status" },
                    null,
                    SpawnFlags.SEARCH_PATH,
                    null,
                    out stdout_text,
                    out stderr_text,
                    out wait_status
                );
            } catch (Error e) {
                warning("Failed to query network devices on startup: %s", e.message);
                return;
            }

            bool found_ethernet = false;

            foreach (string line in stdout_text.split("\n")) {
                if (line.strip().length == 0) {
                    continue;
                }

                string[] parts = line.split(":");
                if (parts.length < 3) {
                    continue;
                }

                string device = parts[0].strip();
                string type = parts[1].strip();
                string state = parts[2].strip();

                if (type != "ethernet" || device == "--") {
                    continue;
                }

                found_ethernet = true;

                run_nmcli_command({
                    "/usr/bin/nmcli",
                    "device",
                    "set",
                    device,
                    "autoconnect",
                    "yes"
                });

                if (state != "connected" && state != "connecting") {
                    run_nmcli_command({
                        "/usr/bin/nmcli",
                        "device",
                        "connect",
                        device
                    });
                }
            }

            if (!found_ethernet) {
                print("No ethernet device found at startup.\n");
            }
        }

        private void run_nmcli_command(string[] argv) {
            string stdout_text;
            string stderr_text;
            int wait_status = 0;

            try {
                Process.spawn_sync(
                    null,
                    argv,
                    null,
                    SpawnFlags.SEARCH_PATH,
                    null,
                    out stdout_text,
                    out stderr_text,
                    out wait_status
                );
            } catch (Error e) {
                warning("Failed to run nmcli startup command: %s", e.message);
            }
        }

        public static int main (string[] args) {
            enable_nouveau_renderer_workaround();
            var app = new QuickSetupApp ();
            return app.run (args);
        }
    }
}
