/*
 * Copyright (C) 2023 Chris Talbot
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

#include "config.h"
#include "geoclue-stumbler-marker.h"
#include "geoclue-stumbler-accuracy-circle.h"

#define _GNU_SOURCE
#include <glib.h>
#include <glib/gi18n.h>
#include <glib-object.h>
#include <math.h>
#include <graphene.h>

struct _GeoclueStumblerMarker
{
  ShumateMarker        parent_instance;

  GeoclueStumblerAcccuracyCircle *accuracy_circle;
  GtkWidget                      *marker_image;

  ShumateSimpleMap          *simple_map;
  unsigned int               accuracy_in_meters;
};

G_DEFINE_TYPE (GeoclueStumblerMarker, geoclue_stumbler_marker, SHUMATE_TYPE_MARKER)

static void
geoclue_stumbler_marker_refresh_acccuracy_circle_geometry (GeoclueStumblerMarker *self)
{
  ShumateViewport  *view_port;
  ShumateMapSource *map_source;
  double zoom_level;
  double lat;
  double lng;
  double meters_per_pixel;
  double circle_diameter;
  ShumateMap *map;

  if (self->accuracy_in_meters <= 1) {
    g_debug ("Accuracy circle is less than or equal to 0, disable");
    gtk_widget_set_visible (GTK_WIDGET (self->accuracy_circle), FALSE);
    return;
  }

  map = shumate_simple_map_get_map(self->simple_map);
  view_port = shumate_map_get_viewport (map);
  map_source = shumate_viewport_get_reference_map_source (view_port);

  zoom_level = shumate_viewport_get_zoom_level (view_port);
  lat = shumate_location_get_latitude (SHUMATE_LOCATION (self));
  lng = shumate_location_get_longitude (SHUMATE_LOCATION (self));

  meters_per_pixel = shumate_map_source_get_meters_per_pixel (map_source,
                                                              zoom_level,
                                                              lat,
                                                              lng);

  circle_diameter = (self->accuracy_in_meters * 2) / meters_per_pixel;

  if (circle_diameter <= 20) {
    g_debug ("Accuracy circle smaller too small, disabling");
    gtk_widget_set_visible (GTK_WIDGET (self->accuracy_circle), FALSE);
    return;
  }

  geoclue_stumbler_accuracy_circle_refresh (self->accuracy_circle, circle_diameter);
  gtk_widget_set_visible (GTK_WIDGET (self->accuracy_circle), TRUE);
}

void
geoclue_stumbler_marker_set_accuracy (GeoclueStumblerMarker *self,
                                      unsigned int accuracy_in_meters)
{
  self->accuracy_in_meters = accuracy_in_meters;

  geoclue_stumbler_marker_refresh_acccuracy_circle_geometry (self);
}

static void
zoom_changed (GeoclueStumblerMarker *self)
{
  geoclue_stumbler_marker_refresh_acccuracy_circle_geometry (self);
}

void
geoclue_stumbler_marker_set_map (GeoclueStumblerMarker *self,
                                 ShumateSimpleMap  *simple_map)
{
  ShumateMap *map;
  ShumateViewport  *view_port;

  self->simple_map = simple_map;

  map = shumate_simple_map_get_map(self->simple_map);
  view_port = shumate_map_get_viewport (map);

  g_signal_connect_swapped (view_port,
                            "notify::zoom-level",
                            G_CALLBACK (zoom_changed),
                            self);
}

static void
geoclue_stumbler_marker_finalize (GObject *object)
{
  GeoclueStumblerMarker *self = (GeoclueStumblerMarker *)object;
  g_clear_object (&self->accuracy_circle);
  g_clear_object (&self->marker_image);

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


static void
geoclue_stumbler_marker_class_init (GeoclueStumblerMarkerClass *klass)
{
  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);

  gtk_widget_class_set_template_from_resource (widget_class,
                                               "/org/kop316/stumbler/geoclue-stumbler-marker.ui");

  gtk_widget_class_bind_template_child (widget_class, GeoclueStumblerMarker, accuracy_circle);
  gtk_widget_class_bind_template_child (widget_class, GeoclueStumblerMarker, marker_image);

  object_class->finalize = geoclue_stumbler_marker_finalize;
}

static void
geoclue_stumbler_marker_init (GeoclueStumblerMarker *self)
{
  g_type_ensure (GEOCLUE_STUMBLER_TYPE_ACCURACY_CIRCLE);

  gtk_widget_init_template (GTK_WIDGET (self));

  geoclue_stumbler_marker_set_accuracy (self, 0);
}

GeoclueStumblerMarker *
geoclue_stumbler_marker_new (void)
{
  return g_object_new (GEOCLUE_STUMBLER_TYPE_MARKER, NULL);
}
