// MLAR GeoTag Recorder with Location File Locator
// Ole Aamot – Aamot Research – GEO-MLAR-2025 – www.gnome.audio

#include <gtk/gtk.h>
#include <gst/gst.h>
#include <gio/gio.h>
#include <glib/gstdio.h>

#define OUTPUT_DIR "./"  // Kan endres til f.eks. "$HOME/MLAR/"

static GstElement *pipeline;
static gboolean recording = FALSE;
static gchar *base_filename = "Lydopptak_%Y-%m-%d_%H-%M-%S";
static GtkEntry *entry_creator, *entry_location, *entry_subject, *entry_journalid, *entry_classcode, *entry_filename;

// Hent posisjon – her fallback, men i ekte kode brukes GeoClue2 via D-Bus
static gchar *geoclue_get_position(void) {
    GError *error = NULL;
    GDBusProxy *manager_proxy = NULL, *client_proxy = NULL, *location_proxy = NULL;
    gchar *location_path = NULL;
    gchar *position_str = NULL;

    // 1. Connect to GeoClue2 Manager
    manager_proxy = g_dbus_proxy_new_for_bus_sync(
        G_BUS_TYPE_SESSION,
        G_DBUS_PROXY_FLAGS_NONE,
        NULL,
        "org.freedesktop.GeoClue2",
        "/org/freedesktop/GeoClue2/Manager",
        "org.freedesktop.GeoClue2.Manager",
        NULL, &error);

    if (!manager_proxy) {
        g_warning("GeoClue2 Manager error: %s", error->message);
        g_clear_error(&error);
        return g_strdup("0.0000,0.0000");
    }

    // 2. Create client
    GVariant *result = g_dbus_proxy_call_sync(manager_proxy, "CreateClient", NULL,
                                              G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
    if (!result) {
        g_warning("CreateClient failed: %s", error->message);
        g_clear_object(&manager_proxy);
        g_clear_error(&error);
        return g_strdup("0.0000,0.0000");
    }

    g_variant_get(result, "(o)", &location_path);
    g_variant_unref(result);
    g_clear_object(&manager_proxy);

    // 3. Set client properties
    client_proxy = g_dbus_proxy_new_for_bus_sync(
        G_BUS_TYPE_SESSION,
        G_DBUS_PROXY_FLAGS_NONE,
        NULL,
        "org.freedesktop.GeoClue2",
        location_path,
        "org.freedesktop.GeoClue2.Client",
        NULL, &error);

    if (!client_proxy) {
        g_warning("GeoClue2 Client error: %s", error->message);
        g_free(location_path);
        g_clear_error(&error);
        return g_strdup("0.0000,0.0000");
    }

    // Set DesktopId (required by GeoClue)
    g_dbus_proxy_set_cached_property(client_proxy, "DesktopId", g_variant_new_string("org.gnome.MLARLocator"));

    // 4. Start location updates
    g_dbus_proxy_call_sync(client_proxy, "Start", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);

    if (error != NULL) {
        g_warning("Start location updates failed: %s", error->message);
        g_free(location_path);
        g_clear_object(&client_proxy);
        g_clear_error(&error);
        return g_strdup("0.0000,0.0000");
    }

    // 5. Poll for location
    for (int i = 0; i < 10; i++) {
        GVariant *location_v = g_dbus_proxy_get_cached_property(client_proxy, "Location");
        if (location_v) {
            gchar *loc_path = NULL;
            g_variant_get(location_v, "o", &loc_path);
            g_variant_unref(location_v);

            location_proxy = g_dbus_proxy_new_for_bus_sync(
                G_BUS_TYPE_SESSION,
                G_DBUS_PROXY_FLAGS_NONE,
                NULL,
                "org.freedesktop.GeoClue2",
                loc_path,
                "org.freedesktop.GeoClue2.Location",
                NULL, &error);

            g_free(loc_path);
            break;
        }
        g_usleep(500000);  // Vent 0.5 sek
    }

    if (!location_proxy) {
        g_warning("Failed to get Location proxy");
        g_free(location_path);
        g_clear_object(&client_proxy);
        return g_strdup("0.0000,0.0000");
    }

    // 6. Fetch Latitude & Longitude
    GVariant *lat_v = g_dbus_proxy_get_cached_property(location_proxy, "Latitude");
    GVariant *lon_v = g_dbus_proxy_get_cached_property(location_proxy, "Longitude");

    if (lat_v && lon_v) {
        gdouble lat = g_variant_get_double(lat_v);
        gdouble lon = g_variant_get_double(lon_v);
        position_str = g_strdup_printf("%.4f,%.4f", lat, lon);
        g_variant_unref(lat_v);
        g_variant_unref(lon_v);
    } else {
        position_str = g_strdup("0.0000,0.0000");
    }

    g_free(location_path);
    g_clear_object(&client_proxy);
    g_clear_object(&location_proxy);
    return position_str;
}

// Generer filbane med katalog og filprefix
static gchar *location_file_locator(const gchar *suffix) {
    return g_strdup_printf(OUTPUT_DIR "%s.%s", base_filename, suffix);
}

// Skriv Noark5-metadatafil
static void write_noark5_xml(const gchar *creator, const gchar *location,
                             const gchar *subject, const gchar *journalid,
                             const gchar *classcode, const gchar *position,
			     const gchar *filename) {
    gchar *xml_filename = location_file_locator("xml");
    gchar *timestamp = g_date_time_format(g_date_time_new_now_local(), "%Y-%m-%dT%H:%M:%S");
    gchar *xml = g_strdup_printf(
        "<?xml version=\"1.0\"?>\n"
        "<noark5:metadata xmlns:noark5=\"https://arkivverket.no/noark5\">\n"
        " <tittel>MLAR-opptak</tittel>\n"
        " <skaper>%s</skaper>\n"
        " <opptakssted>%s</opptakssted>\n"
        " <emneord>%s</emneord>\n"
        " <dato>%s</dato>\n"
        " <journalpostID>%s</journalpostID>\n"
        " <klassifikasjonssystem>%s</klassifikasjonssystem>\n"
        " <posisjon>%s</posisjon>\n"
        " <filnavn>%s</filnavn>\n"
        "</noark5:metadata>\n",
        creator, location, subject, timestamp, journalid, classcode, position, base_filename);

    g_file_set_contents(xml_filename, xml, -1, NULL);
    g_print("Metadata written to %s\n", xml_filename);

    g_free(xml_filename);
    g_free(xml);
    g_free(timestamp);
}

// Start/stop opptak og håndter metadata
static void toggle_record(GtkButton *button, gpointer user_data) {
    GDateTime *now = g_date_time_new_now_local();
    const gchar *creator = gtk_editable_get_text(GTK_EDITABLE(entry_creator));
    const gchar *location = gtk_editable_get_text(GTK_EDITABLE(entry_location));
    const gchar *subject = gtk_editable_get_text(GTK_EDITABLE(entry_subject));
    const gchar *journalid = gtk_editable_get_text(GTK_EDITABLE(entry_journalid));
    const gchar *classcode = gtk_editable_get_text(GTK_EDITABLE(entry_classcode));
    gchar *position = geoclue_get_position();
    // gtk_editable_set_text(GTK_EDITABLE(entry_filename), g_date_time_format(now, "Lydopptak_%Y-%m-%d_%H-%M-%S"));
    if (!recording) {
        GDateTime *now = g_date_time_new_now_local();
        base_filename = g_date_time_format(now, gtk_editable_get_text(GTK_EDITABLE(entry_filename)));
        g_date_time_unref(now);

        gchar *ogg_filename = location_file_locator("ogg");

        pipeline = gst_parse_launch("autoaudiosrc ! audioconvert ! vorbisenc ! oggmux ! filesink name=sink", NULL);
        GstElement *sink = gst_bin_get_by_name(GST_BIN(pipeline), "sink");
        g_object_set(sink, "location", ogg_filename, NULL);
        gst_object_unref(sink);

        gst_element_set_state(pipeline, GST_STATE_PLAYING);
        gtk_button_set_label(button, "Stopp opptak");
        recording = TRUE;
        g_print("Recording to %s...\n", ogg_filename);
        g_free(ogg_filename);
    } else {
        gst_element_set_state(pipeline, GST_STATE_NULL);
        gst_object_unref(pipeline);
        recording = FALSE;
        gtk_button_set_label(button, "Start opptak");

        write_noark5_xml(creator, location, subject, journalid, classcode, position, base_filename);
        g_print("Saved recording and metadata: %s.ogg/.xml\n", base_filename);
        g_free(base_filename);
        base_filename = NULL;
    }
    g_free(position);
}

// Opprett GUI med GTK4
static void activate(GtkApplication *app, gpointer user_data) {
    GDateTime *now = g_date_time_new_now_local();
    GtkWidget *win = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(win), "Multiple Location Audio Recording GeoTag Recorder");
    gtk_window_set_default_size(GTK_WINDOW(win), 480, 360);

    GtkWidget *grid = gtk_grid_new();
    gtk_grid_set_row_spacing(GTK_GRID(grid), 8);
    gtk_widget_set_margin_top(grid, 12);
    gtk_widget_set_margin_start(grid, 12);

    entry_creator = GTK_ENTRY(gtk_entry_new());
    gtk_editable_set_text(GTK_EDITABLE(entry_creator), g_get_real_name());
    entry_location = GTK_ENTRY(gtk_entry_new());
    gtk_editable_set_text(GTK_EDITABLE(entry_location), "Frydenbergveien 56");
    entry_subject = GTK_ENTRY(gtk_entry_new());
    gtk_editable_set_text(GTK_EDITABLE(entry_subject), "Intervju, Gateopptak");
    entry_journalid = GTK_ENTRY(gtk_entry_new());
    gtk_editable_set_text(GTK_EDITABLE(entry_journalid), "2025-001234");
    entry_classcode = GTK_ENTRY(gtk_entry_new());
    gtk_editable_set_text(GTK_EDITABLE(entry_classcode), "GEO-MLAR-2025");
    entry_filename = GTK_ENTRY(gtk_entry_new());
    gtk_editable_set_text(GTK_EDITABLE(entry_filename), base_filename);
    GtkWidget *btn = gtk_button_new_with_label("Start opptak");

    g_signal_connect(btn, "clicked", G_CALLBACK(toggle_record), NULL);

    gtk_grid_attach(GTK_GRID(grid), gtk_label_new("Skaper:"), 0, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(entry_creator), 1, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), gtk_label_new("Sted:"), 0, 1, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(entry_location), 1, 1, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), gtk_label_new("Emneord:"), 0, 2, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(entry_subject), 1, 2, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), gtk_label_new("JournalpostID:"), 0, 3, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(entry_journalid), 1, 3, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), gtk_label_new("Klassifikasjonssystem:"), 0, 4, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(entry_classcode), 1, 4, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), gtk_label_new("Filnavn:"), 0, 5, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(entry_filename), 1, 5, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), btn, 0, 6, 2, 1);

    gtk_window_set_child(GTK_WINDOW(win), grid);
    gtk_window_present(GTK_WINDOW(win));
    g_date_time_unref(now);
}

// Main-funksjon
int main(int argc, char **argv) {
    GtkApplication *app;
    int status;

    gst_init(&argc, &argv);
    app = gtk_application_new("audio.gnome.gnome-audio-locator", G_APPLICATION_DEFAULT_FLAGS);
    g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);
    return status;
}

