/* $Id$

   Copyright (C) 2020-2021 Aamot Software
   Author(s): Ole Aamot <ole@gnome.org>
   License: GNU GPL version 3
   Version: 3.0.0 (2021-11-21)
   Website: http://www.gingerblue.org/

 */

#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <gtk/gtk.h>
#include <gst/gst.h>
#include <gobject/glib-types.h>
#include <gobject/gparam.h>
#include <champlain/champlain.h>
#include <champlain-gtk/champlain-gtk.h>
#include <geoclue.h>
#include <glib/gstdio.h>
#include <glib/gi18n.h>
#include <string.h>
#include "gingerblue.h"

extern GtkWidget *recording_entry;
extern GtkWidget *studio_entry;
extern GtkWidget *musician_entry;
extern GtkWidget *song_entry;
extern GtkWidget *label_entry;

/* Commandline options */
static gint timeout = 30; /* seconds */
static GClueAccuracyLevel accuracy_level = GCLUE_ACCURACY_LEVEL_EXACT;
static gint time_threshold;

static GOptionEntry entries[] =
{
        { "timeout",
          't',
          0,
          G_OPTION_ARG_INT,
          &timeout,
          N_("Exit after T seconds. Default: 30"),
          "T" },
        { "time-threshold",
          'i',
          0,
          G_OPTION_ARG_INT,
          &time_threshold,
          N_("Only report location update after T seconds. "
             "Default: 0 (report new location without any delay)"),
          "T" },
        { "accuracy-level",
          'a',
          0,
          G_OPTION_ARG_INT,
          &accuracy_level,
          N_("Request accuracy level A. "
             "Country = 1, "
             "City = 4, "
             "Neighborhood = 5, "
             "Street = 6, "
             "Exact = 8."),
          "A" },
        { NULL }
};

GClueSimple *simple = NULL;
GClueClient *client = NULL;
GMainLoop *main_loop;

static gchar *
print_location (GClueSimple *simple, ChamplainView *view)
{
        GClueLocation *location;
        gdouble altitude, speed, heading;
        GVariant *timestamp;
        GTimeVal tv = { 0 };
        const char *desc;
	gchar *geostring;
        location = gclue_simple_get_location (simple);
        g_print  ("\nNew location:\n");
        g_print  ("Latitude:    %f°\nLongitude:   %f°\n",
                 gclue_location_get_latitude (location),
                 gclue_location_get_longitude (location));

	champlain_view_center_on (CHAMPLAIN_VIEW (view),
	 			  gclue_location_get_latitude (location),
	 			  gclue_location_get_longitude (location));
	
        altitude = gclue_location_get_altitude (location);
        if (altitude != -G_MAXDOUBLE)
                g_print  ("Altitude:    %f meters\n", altitude);
        speed = gclue_location_get_speed (location);
        if (speed >= 0)
                g_print  ("Speed:       %f meters/second\n", speed);
        heading = gclue_location_get_heading (location);
        if (heading >= 0)
                g_print  ("Heading:     %f°\n", heading);

        desc = gclue_location_get_description (location);
        if (strlen (desc) > 0)
                g_print  ("Description: %s\n", desc);

        timestamp = gclue_location_get_timestamp (location);
        if (timestamp) {
                GDateTime *date_time;
                gchar *str;

                g_variant_get (timestamp, "(tt)", &tv.tv_sec, &tv.tv_usec);

                date_time = g_date_time_new_from_timeval_local (&tv);
                str = g_date_time_format
                      (date_time,
                       "%c (%s seconds since the Epoch)");
                g_date_time_unref (date_time);

                g_print  ("Timestamp:   %s\n", str);
                g_free (str);
        }
	geostring = g_strconcat ("  <glat>", gclue_location_get_latitude (location), "</glat>",
				 "  <glon>", gclue_location_get_longitude (location), "</glon>", 
				 "  <galt>", gclue_location_get_altitude (location), "</galt>",
				 NULL);
	return geostring;
}

static gboolean
on_location_timeout (gpointer user_data)
{
        g_clear_object (&client);
        g_clear_object (&simple);
        g_main_loop_quit (main_loop);

        return FALSE;
}

static void
on_client_active_notify (GClueClient *client,
                         GParamSpec *pspec,
                         gpointer    user_data)
{
        if (gclue_client_get_active (client))
                return;

        g_print ("Geolocation disabled. Quitting..\n");
        on_location_timeout (NULL);
}

static void
on_simple_ready (GObject      *source_object,
                 GAsyncResult *res,
                 gpointer      user_data)
{
        GError *error = NULL;

        simple = gclue_simple_new_finish (res, &error);
        if (error != NULL) {
            g_critical ("Failed to connect to GeoClue2 service: %s", error->message);

            exit (-1);
        }
        client = gclue_simple_get_client (simple);
        if (client) {
                g_object_ref (client);
                g_print ("Client object: %s\n",
                         g_dbus_proxy_get_object_path (G_DBUS_PROXY (client)));

                g_signal_connect (client,
                                  "notify::active",
                                  G_CALLBACK (on_client_active_notify),
                                  NULL);
        }
        print_location (simple, user_data);

        g_signal_connect (simple,
                          "notify::location",
                          G_CALLBACK (print_location),
                          user_data);
}


gchar *studio_location_navigate (ChamplainView *view, gpointer *data) {
        GClueLocation *location;
	GClueSimple *simple;
        gdouble altitude, speed, heading;
	GVariant *timestamp;
        GTimeVal tv = { 0 };
	gclue_simple_new ("gingerblue",
			  accuracy_level,
			  time_threshold,
			  on_simple_ready,
			  CHAMPLAIN_VIEW (view));
	gtk_entry_set_text (GTK_ENTRY(data), print_location (simple, NULL));
	return print_location (simple, NULL);
}
