/* urc-application.c
 *
 * Copyright 2009-2025 Daniele Napolitano <dnax88@gmail.com>
 *
 * 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 <http://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

#include "config.h"

#include <glib.h>
#include <glib/gi18n-lib.h>

#include <gtk/gtk.h>

#include "urc-application.h"
#include "urc-gui.h"
#include "urc-upnp.h"

gboolean opt_debug = FALSE;

struct _UrcApplication
{
    GtkApplication parent_instance;
    GtkWidget *main_window;

    UrcOptions  opts;
    GSettings *settings;

    RouterInfo          *router;
};

G_DEFINE_TYPE (UrcApplication, urc_application, GTK_TYPE_APPLICATION);

GSettings *
urc_application_get_settings (UrcApplication *self)
{
    g_return_val_if_fail(URC_IS_APPLICATION(self), NULL);
    return self->settings;
}

void
urc_application_set_router (UrcApplication *self, RouterInfo *router)
{
    self->router = router;
}

RouterInfo *
urc_application_get_router (UrcApplication *self)
{
    g_return_val_if_fail(URC_IS_APPLICATION(self), NULL);
    return self->router;
}

const UrcOptions *
urc_application_get_options (UrcApplication *self)
{
    g_return_val_if_fail (URC_IS_APPLICATION(self), NULL);
    return &self->opts;
}

static void
urc_application_activate (GApplication *_app)
{
    UrcApplication *app = URC_APPLICATION (_app);

    /* Initialize the GUI */
    if (app->main_window == NULL)
        app->main_window = urc_gui_init (app);

    gtk_window_present_with_time (GTK_WINDOW (app->main_window), gtk_get_current_event_time());
}

static void
urc_application_startup (GApplication *app)
{
    UrcApplication *self = URC_APPLICATION(app);

    G_APPLICATION_CLASS (urc_application_parent_class)->startup(app);

    /* Initialize the UPnP subsystem */
    upnp_init();

    g_set_application_name(_("UPnP Router Control"));
    gtk_window_set_default_icon_name (APPLICATION_ID);

    self->settings = g_settings_new (APPLICATION_ID);
}

GtkApplication *
urc_application_new (void)
{
    return g_object_new (URC_TYPE_APPLICATION,
                         "application-id", APPLICATION_ID,
                         "flags", G_APPLICATION_HANDLES_COMMAND_LINE,
                         "resource-base-path", URC_RESOURCE_BASE,
                         NULL);
}

static void
urc_application_init (UrcApplication *self)
{
    self->main_window   = NULL;
    self->opts.bind_if  = NULL;
    self->opts.bind_port = 0;
    self->opts.hide_ext_ip_address = FALSE;

    self->settings      = NULL;

    self->router        = NULL;
}


static gint
urc_application_command_line (GApplication            *app,
                              GApplicationCommandLine *cmdline)
{
    UrcApplication *self = URC_APPLICATION (app);

    int argc;
    char **argv = g_application_command_line_get_arguments (cmdline, &argc);

    static gboolean opt_version = FALSE;

    /* Options schema */
    GOptionEntry entries[] =
    {
        { "if", 'i', 0, G_OPTION_ARG_STRING, &self->opts.bind_if, "The network interface used (all if omitted)", NULL },
        { "port", 'p', 0, G_OPTION_ARG_INT, &self->opts.bind_port, "Use a specific source port", NULL },
        { "hide-ext-ip", 0, 0, G_OPTION_ARG_NONE, &self->opts.hide_ext_ip_address, "Hide external IP address from displaying", NULL },
        { "version", 0, 0, G_OPTION_ARG_NONE, &opt_version, "Show version and exit", NULL },
        { "debug", 0, 0, G_OPTION_ARG_NONE, &opt_debug, "Allow debug messages", NULL },
        { NULL }
    };

    /* commandline options */
    GOptionContext *context = g_option_context_new ("- A simple program to manage UPnP IGD compliant routers");
    g_option_context_add_main_entries (context, entries, NULL);

    GError *error = NULL;
    if (!g_option_context_parse (context, &argc, &argv, &error)) {
        g_application_command_line_printerr (
            cmdline,
            "Error parsing options: %s\n",
            error->message
        );
        g_error_free (error);
        g_option_context_free (context);
        g_strfreev (argv);
        return 1;
    }

    if (opt_version) {
        g_application_command_line_print (
            cmdline,
            "%s %s\n", PACKAGE, VERSION
        );

        g_option_context_free (context);
        g_strfreev (argv);

        return EXIT_SUCCESS;
    }

    g_application_activate (app);

    g_option_context_free (context);
    g_strfreev (argv);

    return EXIT_SUCCESS;
}

static void
urc_application_finalize (GObject *object)
{
    UrcApplication *self = URC_APPLICATION(object);

    g_clear_object(&self->settings);

    G_OBJECT_CLASS(urc_application_parent_class)->finalize(object);
}

static void
urc_application_class_init (UrcApplicationClass *klass)
{
    GObjectClass      *object_class = G_OBJECT_CLASS (klass);
    GApplicationClass *app_class    = G_APPLICATION_CLASS (klass);

    object_class->finalize   = urc_application_finalize;
    app_class->startup       = urc_application_startup;
    app_class->activate      = urc_application_activate;
    app_class->command_line  = urc_application_command_line;
}

