/*
 * overview-view.c
 * Copyright (C) 2021 Zwarf <zwarf@mail.de>
 *
 * 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/>.
 */

#include "overview-view.h"
#include "calculations/calculations_transformations.h"
#include "calculations/calculations_sun.h"
#include "calculations/calculations_moon.h"
#include "calculations/calculations_milky_way.h"
#include "map/draw-layer.h"
#include "map/marker.h"
#include <libgweather/gweather.h>

#define LENGTH_SCALE_FACTOR 0.38
#define ICON_SIZE_SMALL 32
#define ICON_SIZE_LARGE 48

struct _PicplannerOverview
{
  GtkBox              parent_instance;

  GtkWidget           *basic_information;

  GtkWidget           *switch_sun;
  GtkWidget           *switch_moon;
  GtkWidget           *switch_milky_way;

  GtkWidget           *label_sun_rise;
  GtkWidget           *label_sun_set;
  GtkWidget           *label_moon_rise;
  GtkWidget           *label_moon_set;
  GtkWidget           *label_milky_way_rise;
  GtkWidget           *label_milky_way_set;
  GtkWidget           *label_elevation_sun;
  GtkWidget           *label_elevation_moon;
  GtkWidget           *label_elevation_milky_way;
  GtkWidget           *label_azimuth_sun;
  GtkWidget           *label_azimuth_moon;
  GtkWidget           *label_azimuth_milky_way;

  ShumateSimpleMap    *map;
  ShumateViewport     *viewport;

  PicplannerMarker    *pp_marker_center;
  PicplannerDrawLayer *pp_layer_center;

  PicplannerMarker    *pp_marker_sun;
  PicplannerDrawLayer *pp_layer_sun;
  PicplannerDrawLayer *pp_layer_sun_rise_set;

  PicplannerMarker    *pp_marker_moon;
  PicplannerDrawLayer *pp_layer_moon;
  PicplannerDrawLayer *pp_layer_moon_rise_set;

  PicplannerMarker    *pp_marker_milky_way;
  PicplannerDrawLayer *pp_layer_milky_way;
  PicplannerDrawLayer *pp_layer_milky_way_rise_set;

  GSettings           *settings;

  gint                input_timeout_id;
  gint                input_rebounce_timeout_id;
  guint               input_count;
  gboolean            input_new;
  gboolean            input_currently;

};


G_DEFINE_TYPE (PicplannerOverview, picplanner_overview, GTK_TYPE_BOX)
static gboolean
input_rebounce_reset_signal (gpointer user_data)
{
  PicplannerOverview *overview = PICPLANNER_OVERVIEW (user_data);
  overview->input_currently = FALSE;
  g_source_remove (overview->input_rebounce_timeout_id);
  return TRUE;
}

static gboolean
input_timeout_signal (gpointer user_data)
{
  PicplannerOverview *overview = PICPLANNER_OVERVIEW (user_data);

  if (overview->input_count == 0)
    {
      overview->input_new = TRUE;
      overview->input_currently = TRUE;
      overview->input_rebounce_timeout_id = g_timeout_add (5,
                                                           input_rebounce_reset_signal,
                                                           overview);
      g_settings_set_double (overview->settings,
                             "longitude" ,
                             shumate_location_get_longitude (SHUMATE_LOCATION(overview->viewport)));
      g_settings_set_double (overview->settings,
                             "latitude" ,
                             shumate_location_get_latitude (SHUMATE_LOCATION(overview->viewport)));
      g_source_remove (overview->input_timeout_id);
    }
  overview->input_count = 0;

  return TRUE;
}
static void
input_changed (GtkWidget *self,
               gpointer user_data,
               gpointer data_overview)
{
  (void) user_data;
  PicplannerOverview *overview;
  overview = PICPLANNER_OVERVIEW (data_overview);

  if (!overview->input_currently)
    {
      if (!G_IS_SETTINGS(self) && !PICPLANNER_IS_OVERVIEW (self))
        {
          if (overview->input_new)
            {
              overview->input_new = FALSE;
              overview->input_timeout_id = g_timeout_add (100,
                                                          input_timeout_signal,
                                                          overview);
            }
          overview->input_count++;
          picplanner_overview_remove_map_content (overview);
        }
      else
        {
          shumate_location_set_location (SHUMATE_LOCATION (overview->viewport),
                                         g_settings_get_double (overview->settings, "latitude"),
                                         g_settings_get_double (overview->settings, "longitude"));
        }
    }
}

/*
 * Set the coordinates of the sun including the index of the sunrise,
 * upper culmination, sunset and lower culmination as well as the current index.
 * The overview page then showes sunrise, sunset, current elevation and current azimuth.
 */
void
picplanner_overview_set_current_coordinates_sun (PicplannerOverview *overview,
                                                 double             *array_coordinates_sun,
                                                 int                *rise_upper_set_index,
                                                 int                current_index,
                                                 GDateTime          *date_time)
{
  char *char_elevation_sun;
  char *char_azimuth_sun;
  char *char_sun_rise;
  char *char_sun_set;

  GDateTime *date_time_noon;
  GDateTime *date_time_rise;
  GDateTime *date_time_set;

  date_time_noon = g_date_time_new (g_date_time_get_timezone (date_time),
                                    g_date_time_get_year (date_time),
                                    g_date_time_get_month (date_time),
                                    g_date_time_get_day_of_month (date_time),
                                    12, 0, 0);


  date_time_rise = g_date_time_add_minutes (date_time_noon, rise_upper_set_index[0]*24*60/NUM_DATA_POINTS-12*60);
  date_time_set = g_date_time_add_minutes (date_time_noon, rise_upper_set_index[2]*24*60/NUM_DATA_POINTS-12*60);

  if (rise_upper_set_index[0]>0)
    {
      char_sun_rise = g_strdup_printf ("%02d:%02d",
                                       g_date_time_get_hour (date_time_rise),
                                       g_date_time_get_minute (date_time_rise));
    }
  else
    {
      char_sun_rise = g_strdup_printf ("--:--");
    }

  if (rise_upper_set_index[2]>0)
    {
      char_sun_set = g_strdup_printf ("%02d:%02d",
                                      g_date_time_get_hour (date_time_set),
                                      g_date_time_get_minute (date_time_set));
    }
  else
    {
      char_sun_set = g_strdup_printf ("--:--");
    }

  char_elevation_sun = g_strdup_printf ("%.0f\u00B0", array_coordinates_sun[current_index*2+1]);
  char_azimuth_sun = g_strdup_printf ("%.0f\u00B0", array_coordinates_sun[current_index*2]);

  gtk_label_set_text (GTK_LABEL (overview->label_sun_rise), char_sun_rise);
  gtk_label_set_text (GTK_LABEL (overview->label_sun_set), char_sun_set);
  gtk_label_set_text (GTK_LABEL (overview->label_elevation_sun), char_elevation_sun);
  gtk_label_set_text (GTK_LABEL (overview->label_azimuth_sun), char_azimuth_sun);

  g_date_time_unref (date_time_rise);
  g_date_time_unref (date_time_set);

  g_free (char_sun_rise);
  g_free (char_sun_set);
  g_free (char_elevation_sun);
  g_free (char_azimuth_sun);
}


/*
 * Set the coordinates of the moon including the index of the rise,
 * upper culmination, set and lower culmination as well as the current index.
 * The overview page then showes rise, set, current elevation and current azimuth
 * of the moon.
 */
void
picplanner_overview_set_current_coordinates_moon (PicplannerOverview  *overview,
                                                  double              *array_coordinates_moon,
                                                  int                 *rise_upper_set_index,
                                                  int                 current_index,
                                                  GDateTime           *date_time)
{
  char *char_elevation_moon;
  char *char_azimuth_moon;
  char *char_moon_rise;
  char *char_moon_set;

  GDateTime *date_time_noon;
  GDateTime *date_time_rise;
  GDateTime *date_time_set;

  date_time_noon = g_date_time_new (g_date_time_get_timezone (date_time),
                                    g_date_time_get_year (date_time),
                                    g_date_time_get_month (date_time),
                                    g_date_time_get_day_of_month (date_time),
                                    12, 0, 0);

  date_time_rise = g_date_time_add_minutes (date_time_noon, rise_upper_set_index[0]*24*60/NUM_DATA_POINTS-12*60);
  date_time_set = g_date_time_add_minutes (date_time_noon, rise_upper_set_index[2]*24*60/NUM_DATA_POINTS-12*60);

  if (rise_upper_set_index[0]>0)
    {
      char_moon_rise = g_strdup_printf ("%02d:%02d",
                                        g_date_time_get_hour (date_time_rise),
                                        g_date_time_get_minute (date_time_rise));
    }
  else
    {
      char_moon_rise = g_strdup_printf ("--:--");
    }

  if (rise_upper_set_index[2]>0)
    {
      char_moon_set = g_strdup_printf ("%02d:%02d",
                                       g_date_time_get_hour (date_time_set),
                                       g_date_time_get_minute (date_time_set));
    }
  else
    {
      char_moon_set = g_strdup_printf ("--:--");
    }

  char_elevation_moon = g_strdup_printf ("%.0f\u00B0", array_coordinates_moon[current_index*2+1]);
  char_azimuth_moon = g_strdup_printf ("%.0f\u00B0", array_coordinates_moon[current_index*2]);

  gtk_label_set_text (GTK_LABEL (overview->label_moon_rise), char_moon_rise);
  gtk_label_set_text (GTK_LABEL (overview->label_moon_set), char_moon_set);
  gtk_label_set_text (GTK_LABEL (overview->label_elevation_moon), char_elevation_moon);
  gtk_label_set_text (GTK_LABEL (overview->label_azimuth_moon), char_azimuth_moon);

  g_date_time_unref (date_time_rise);
  g_date_time_unref (date_time_set);


  g_free (char_moon_rise);
  g_free (char_moon_set);
  g_free (char_elevation_moon);
  g_free (char_azimuth_moon);
}


/*
 * Set the coordinates of the moon including the index of the rise,
 * upper culmination, set and lower culmination as well as the current index.
 * The overview page then showes rise, set, current elevation and current azimuth
 * of the moon.
 */
void
picplanner_overview_set_current_coordinates_milky_way (PicplannerOverview *overview,
                                                       double             *array_coordinates_milky_way,
                                                       int                *rise_upper_set_index,
                                                       int                current_index,
                                                       GDateTime          *date_time)
{
  char *char_elevation_milky_way;
  char *char_azimuth_milky_way;
  char *char_milky_way_rise;
  char *char_milky_way_set;

  GDateTime *date_time_noon;
  GDateTime *date_time_rise;
  GDateTime *date_time_set;

  date_time_noon = g_date_time_new (g_date_time_get_timezone (date_time),
                                    g_date_time_get_year (date_time),
                                    g_date_time_get_month (date_time),
                                    g_date_time_get_day_of_month (date_time),
                                    12, 0, 0);

  date_time_rise = g_date_time_add_minutes (date_time_noon, rise_upper_set_index[0]*24*60/NUM_DATA_POINTS-12*60);
  date_time_set = g_date_time_add_minutes (date_time_noon, rise_upper_set_index[2]*24*60/NUM_DATA_POINTS-12*60);

  if (rise_upper_set_index[0]>0)
    {
      char_milky_way_rise = g_strdup_printf ("%02d:%02d",
                                             g_date_time_get_hour (date_time_rise),
                                             g_date_time_get_minute (date_time_rise));
    }
  else
    {
      char_milky_way_rise = g_strdup_printf ("--:--");
    }

  if (rise_upper_set_index[2]>0)
    {
      char_milky_way_set = g_strdup_printf ("%02d:%02d",
                                            g_date_time_get_hour (date_time_set),
                                            g_date_time_get_minute (date_time_set));
    }
  else
    {
      char_milky_way_set = g_strdup_printf ("--:--");
    }

  char_elevation_milky_way = g_strdup_printf ("%.0f\u00B0", array_coordinates_milky_way[current_index*2+1]);
  char_azimuth_milky_way = g_strdup_printf ("%.0f\u00B0", array_coordinates_milky_way[current_index*2]);

  gtk_label_set_text (GTK_LABEL (overview->label_milky_way_rise), char_milky_way_rise);
  gtk_label_set_text (GTK_LABEL (overview->label_milky_way_set), char_milky_way_set);
  gtk_label_set_text (GTK_LABEL (overview->label_elevation_milky_way), char_elevation_milky_way);
  gtk_label_set_text (GTK_LABEL (overview->label_azimuth_milky_way), char_azimuth_milky_way);

  g_date_time_unref (date_time_rise);
  g_date_time_unref (date_time_set);

  g_free (char_milky_way_rise);
  g_free (char_milky_way_set);
  g_free (char_elevation_milky_way);
  g_free (char_azimuth_milky_way);
}


/*
 * Removes all the content on the map.
 */
void
picplanner_overview_remove_map_content (PicplannerOverview *overview)
{
  picplanner_draw_layer_remove_all (overview->pp_layer_sun);
  picplanner_draw_layer_remove_all (overview->pp_layer_sun_rise_set);
  picplanner_draw_layer_remove_all (overview->pp_layer_moon);
  picplanner_draw_layer_remove_all (overview->pp_layer_moon_rise_set);
  picplanner_draw_layer_remove_all (overview->pp_layer_milky_way);
  picplanner_draw_layer_remove_all (overview->pp_layer_milky_way_rise_set);
}


/*
 * Redraws the center icon on the map.
 */
void
picplanner_overview_update_map_center (PicplannerOverview *overview)
{
  GtkWidget *image_center;

  picplanner_draw_layer_remove_all (overview->pp_layer_center);

  image_center = gtk_image_new_from_icon_name ("pin");
  gtk_image_set_pixel_size (GTK_IMAGE (image_center), ICON_SIZE_LARGE);

  picplanner_marker_set_location (overview->pp_marker_center, 1./2., 1./2., 0, -ICON_SIZE_LARGE/2+8);
  picplanner_marker_set_child (overview->pp_marker_center, image_center);
  picplanner_draw_layer_add_marker (overview->pp_layer_center, overview->pp_marker_center);
}


/*
 * Redraws the information of the sun on the map.
 */
void
picplanner_overview_update_map_sun (PicplannerOverview  *overview,
                                    double              *array_coordinates_sun,
                                    int                 current_index,
                                    int                 *rise_upper_set_sun)
{
  int sun_stroke_width = 6;
  int sun_rise_set_stroke_width = 9;
  static GdkRGBA sun_color = {1., 0.9, 0., 1};
  static GdkRGBA sun_rise_set_color = {1., 0.8, 0., 0.5};

  double x_sun, y_sun;
  double x_sunrise, y_sunrise;
  double x_sunset, y_sunset;
  double azimuth_sun, azimuth_sunrise, azimuth_sunset;

  gboolean visible_sun = TRUE;
  GtkWidget *image_sun;

  picplanner_draw_layer_remove_all (overview->pp_layer_sun);
  picplanner_draw_layer_remove_all (overview->pp_layer_sun_rise_set);

  if (array_coordinates_sun[current_index*2+1]<0)
    visible_sun = FALSE;
  image_sun = gtk_image_new_from_icon_name ("sun");
  gtk_image_set_pixel_size (GTK_IMAGE (image_sun), ICON_SIZE_LARGE);
  gtk_widget_set_visible (image_sun, visible_sun);

  azimuth_sun = array_coordinates_sun[current_index*2];
  x_sun = 1./2. + sin(calc_deg_to_rad (azimuth_sun)) * LENGTH_SCALE_FACTOR;
  y_sun = 1./2. - cos(calc_deg_to_rad (azimuth_sun)) * LENGTH_SCALE_FACTOR;

  azimuth_sunrise = array_coordinates_sun[rise_upper_set_sun[0]*2];
  x_sunrise = 1./2. + sin(calc_deg_to_rad (azimuth_sunrise)) * LENGTH_SCALE_FACTOR;
  y_sunrise = 1./2. - cos(calc_deg_to_rad (azimuth_sunrise)) * LENGTH_SCALE_FACTOR;

  azimuth_sunset = array_coordinates_sun[rise_upper_set_sun[2]*2];
  x_sunset = 1./2. + sin(calc_deg_to_rad (azimuth_sunset)) * LENGTH_SCALE_FACTOR;
  y_sunset = 1./2. - cos(calc_deg_to_rad (azimuth_sunset)) * LENGTH_SCALE_FACTOR;


  picplanner_marker_set_location (overview->pp_marker_sun, x_sun, y_sun, 0, 0);
  picplanner_marker_set_child (overview->pp_marker_sun, image_sun);
  picplanner_draw_layer_add_marker (overview->pp_layer_sun, overview->pp_marker_sun);


  picplanner_draw_layer_add_node_coordinates (overview->pp_layer_sun, 1./2., 1./2.);
  picplanner_draw_layer_add_node_coordinates (overview->pp_layer_sun, x_sun, y_sun);
  picplanner_draw_layer_set_stroke_color (overview->pp_layer_sun, &sun_color);
  picplanner_draw_layer_set_stroke_width (overview->pp_layer_sun, sun_stroke_width);
  picplanner_draw_layer_set_stroke (overview->pp_layer_sun, visible_sun);

  if (rise_upper_set_sun[0]!=-1)
    picplanner_draw_layer_add_node_coordinates (overview->pp_layer_sun_rise_set, x_sunrise, y_sunrise);
  picplanner_draw_layer_add_node_coordinates (overview->pp_layer_sun_rise_set, 1./2., 1./2.);
  if (rise_upper_set_sun[2]!=-1)
    picplanner_draw_layer_add_node_coordinates (overview->pp_layer_sun_rise_set, x_sunset, y_sunset);
  picplanner_draw_layer_set_stroke_color (overview->pp_layer_sun_rise_set, &sun_rise_set_color);
  picplanner_draw_layer_set_stroke_width (overview->pp_layer_sun_rise_set, sun_rise_set_stroke_width);
}


/*
 * Redraws the information of the moon on the map.
 */
void
picplanner_overview_update_map_moon (PicplannerOverview  *overview,
                                     double              *array_coordinates_moon,
                                     int                 current_index,
                                     int                 *rise_upper_set_moon,
                                     int                 phase_moon_index)
{
  int moon_stroke_width = 6;
  int moon_rise_set_stroke_width = 9;
  static GdkRGBA moon_color = {0.8, 0.8, 0.8, 1};
  static GdkRGBA moon_rise_set_color = {0.5, 0.5, 0.5, 0.5};

  double x_moon, y_moon;
  double x_moonrise, y_moonrise;
  double x_moonset, y_moonset;
  double azimuth_moon, azimuth_moonrise, azimuth_moonset;

  gboolean visible_moon = TRUE;
  GtkWidget *image_moon;

  picplanner_draw_layer_remove_all (overview->pp_layer_moon);
  picplanner_draw_layer_remove_all (overview->pp_layer_moon_rise_set);

  if (array_coordinates_moon[current_index*2+1]<0)
    visible_moon = FALSE;

  if (phase_moon_index == 0)
    image_moon = gtk_image_new_from_icon_name ("moon-full");
  else if (phase_moon_index == 1)
    image_moon = gtk_image_new_from_icon_name ("moon-waxing");
  else if (phase_moon_index == 2)
    image_moon = gtk_image_new_from_icon_name ("moon-waning");
  else
    image_moon = gtk_image_new_from_icon_name ("moon-new");
  gtk_image_set_pixel_size (GTK_IMAGE (image_moon), ICON_SIZE_LARGE);
  gtk_widget_set_visible (image_moon, visible_moon);

  azimuth_moon = array_coordinates_moon[current_index*2];
  x_moon = 1./2. + sin(calc_deg_to_rad (azimuth_moon)) * LENGTH_SCALE_FACTOR;
  y_moon = 1./2. - cos(calc_deg_to_rad (azimuth_moon)) * LENGTH_SCALE_FACTOR;

  azimuth_moonrise = array_coordinates_moon[rise_upper_set_moon[0]*2];
  x_moonrise = 1./2. + sin(calc_deg_to_rad (azimuth_moonrise)) * LENGTH_SCALE_FACTOR;
  y_moonrise = 1./2. - cos(calc_deg_to_rad (azimuth_moonrise)) * LENGTH_SCALE_FACTOR;

  azimuth_moonset = array_coordinates_moon[rise_upper_set_moon[2]*2];
  x_moonset = 1./2. + sin(calc_deg_to_rad (azimuth_moonset)) * LENGTH_SCALE_FACTOR;
  y_moonset = 1./2. - cos(calc_deg_to_rad (azimuth_moonset)) * LENGTH_SCALE_FACTOR;

  picplanner_marker_set_location (overview->pp_marker_moon, x_moon, y_moon, 0 , 0);
  picplanner_marker_set_child (overview->pp_marker_moon, image_moon);
  picplanner_draw_layer_add_marker (overview->pp_layer_moon, overview->pp_marker_moon);

  picplanner_draw_layer_add_node_coordinates (overview->pp_layer_moon, 1./2., 1./2.);
  picplanner_draw_layer_add_node_coordinates (overview->pp_layer_moon, x_moon, y_moon);
  picplanner_draw_layer_set_stroke_color (overview->pp_layer_moon, &moon_color);
  picplanner_draw_layer_set_stroke_width (overview->pp_layer_moon, moon_stroke_width);
  picplanner_draw_layer_set_stroke (overview->pp_layer_moon, visible_moon);

  if (rise_upper_set_moon[0]!=-1)
    picplanner_draw_layer_add_node_coordinates (overview->pp_layer_moon_rise_set, x_moonrise, y_moonrise);
  picplanner_draw_layer_add_node_coordinates (overview->pp_layer_moon_rise_set, 1./2., 1./2.);
  if (rise_upper_set_moon[2]!=-1)
    picplanner_draw_layer_add_node_coordinates (overview->pp_layer_moon_rise_set, x_moonset, y_moonset);
  picplanner_draw_layer_set_stroke_color (overview->pp_layer_moon_rise_set, &moon_rise_set_color);
  picplanner_draw_layer_set_stroke_width (overview->pp_layer_moon_rise_set, moon_rise_set_stroke_width);
}


/*
 * Redraws the information of the milky way on the map.
 */
void
picplanner_overview_update_map_milky_way (PicplannerOverview  *overview,
                                          double              *array_coordinates_milky_way,
                                          int                 current_index,
                                          int                 *rise_upper_set_milky_way)
{
  int milky_way_stroke_width = 6;
  int milky_way_rise_set_stroke_width = 9;
  static GdkRGBA milky_way_color = {0.2, 0.2, 0.7, 1};
  static GdkRGBA milky_way_rise_set_color = {0.0, 0.0, 0.4, 0.5};

  double x_milky_way, y_milky_way;
  double x_milky_way_rise, y_milky_way_rise;
  double x_milky_way_set, y_milky_way_set;
  double azimuth_milky_way, azimuth_milky_way_rise, azimuth_milky_way_set;

  gboolean visible_milky_way = TRUE;
  GtkWidget *image_milky_way;

  picplanner_draw_layer_remove_all (overview->pp_layer_milky_way);
  picplanner_draw_layer_remove_all (overview->pp_layer_milky_way_rise_set);

  if (array_coordinates_milky_way[current_index*2+1]<0)
    visible_milky_way = FALSE;
  image_milky_way = gtk_image_new_from_icon_name ("milky-way-color");
  gtk_image_set_pixel_size (GTK_IMAGE (image_milky_way), ICON_SIZE_LARGE);
  gtk_widget_set_visible (image_milky_way, visible_milky_way);

  azimuth_milky_way = array_coordinates_milky_way[current_index*2];
  x_milky_way = 1./2. + sin(calc_deg_to_rad (azimuth_milky_way)) * LENGTH_SCALE_FACTOR;
  y_milky_way = 1./2. - cos(calc_deg_to_rad (azimuth_milky_way)) * LENGTH_SCALE_FACTOR;

  azimuth_milky_way_rise = array_coordinates_milky_way[rise_upper_set_milky_way[0]*2];
  x_milky_way_rise = 1./2. + sin(calc_deg_to_rad (azimuth_milky_way_rise)) * LENGTH_SCALE_FACTOR;
  y_milky_way_rise = 1./2. - cos(calc_deg_to_rad (azimuth_milky_way_rise)) * LENGTH_SCALE_FACTOR;

  azimuth_milky_way_set = array_coordinates_milky_way[rise_upper_set_milky_way[2]*2];
  x_milky_way_set = 1./2. + sin(calc_deg_to_rad (azimuth_milky_way_set)) * LENGTH_SCALE_FACTOR;
  y_milky_way_set = 1./2. - cos(calc_deg_to_rad (azimuth_milky_way_set)) * LENGTH_SCALE_FACTOR;

  picplanner_marker_set_location (overview->pp_marker_milky_way, x_milky_way, y_milky_way, 0, 0);
  picplanner_marker_set_child (overview->pp_marker_milky_way, image_milky_way);
  picplanner_draw_layer_add_marker (overview->pp_layer_milky_way, overview->pp_marker_milky_way);

  picplanner_draw_layer_add_node_coordinates (overview->pp_layer_milky_way, 1./2., 1./2.);
  picplanner_draw_layer_add_node_coordinates (overview->pp_layer_milky_way, x_milky_way, y_milky_way);
  picplanner_draw_layer_set_stroke_color (overview->pp_layer_milky_way, &milky_way_color);
  picplanner_draw_layer_set_stroke_width (overview->pp_layer_milky_way, milky_way_stroke_width);
  picplanner_draw_layer_set_stroke (overview->pp_layer_milky_way, visible_milky_way);

  if (rise_upper_set_milky_way[0]!=-1)
    picplanner_draw_layer_add_node_coordinates (overview->pp_layer_milky_way_rise_set, x_milky_way_rise, y_milky_way_rise);
  picplanner_draw_layer_add_node_coordinates (overview->pp_layer_milky_way_rise_set, 1./2., 1./2.);
  if (rise_upper_set_milky_way[2]!=-1)
    picplanner_draw_layer_add_node_coordinates (overview->pp_layer_milky_way_rise_set, x_milky_way_set, y_milky_way_set);
  picplanner_draw_layer_set_stroke_color (overview->pp_layer_milky_way_rise_set, &milky_way_rise_set_color);
  picplanner_draw_layer_set_stroke_width (overview->pp_layer_milky_way_rise_set, milky_way_rise_set_stroke_width);
}


/*
 * Changes which scale should be visible on the map.
 * No scale, metric scale, imperial scale or both scales.
 */
static void
shumate_map_metric_imperial_scale (GSettings  *settings,
                                   gchar      *key,
                                   gpointer   user_data)
{
  (void) settings;
  (void) key;
  PicplannerOverview *overview = user_data;
  ShumateScale *scale;
  gboolean metric;
  gboolean imperial;

  scale = shumate_simple_map_get_scale (overview->map);
  metric = g_settings_get_boolean (settings, "map-unit-metric");
  imperial = g_settings_get_boolean (settings, "map-unit-imperial");

  gtk_widget_set_visible (GTK_WIDGET (scale), TRUE);

  if (metric && imperial)
    shumate_scale_set_unit (scale, SHUMATE_UNIT_BOTH);
  else if (metric)
    shumate_scale_set_unit (scale, SHUMATE_UNIT_METRIC);
  else if (imperial)
    shumate_scale_set_unit (scale, SHUMATE_UNIT_IMPERIAL);
  else
    gtk_widget_set_visible (GTK_WIDGET (scale), FALSE);

}


static void
picplanner_overview_init (PicplannerOverview *overview)
{
  ShumateMapSource *map_source;
  ShumateMapSourceRegistry *registry;

  gtk_widget_init_template (GTK_WIDGET (overview));

  overview->settings = g_settings_new ("de.zwarf.picplanner");

  /*
   * Initialise values necessary for displaying the map
   */
  registry = shumate_map_source_registry_new_with_defaults ();
  map_source = shumate_map_source_registry_get_by_id (registry, SHUMATE_MAP_SOURCE_OSM_MAPNIK);
  overview->viewport = shumate_simple_map_get_viewport (overview->map);

  shumate_map_metric_imperial_scale (overview->settings, NULL, overview);
  shumate_map_source_set_license (map_source, "\xC2\xA9 OpenStreetMap Contributors");

  shumate_simple_map_set_map_source (overview->map, map_source);


  // Initialise drawing layers for the map
  overview->pp_marker_center = picplanner_marker_new ();
  g_object_ref (overview->pp_marker_center);

  overview->pp_marker_milky_way = picplanner_marker_new ();
  g_object_ref (overview->pp_marker_milky_way);
  overview->pp_layer_milky_way = picplanner_draw_layer_new (overview->viewport);
  overview->pp_layer_milky_way_rise_set = picplanner_draw_layer_new (overview->viewport);


  overview->pp_marker_moon = picplanner_marker_new ();
  g_object_ref (overview->pp_marker_moon);
  overview->pp_layer_moon = picplanner_draw_layer_new (overview->viewport);
  overview->pp_layer_moon_rise_set = picplanner_draw_layer_new (overview->viewport);


  overview->pp_marker_sun = picplanner_marker_new ();
  g_object_ref (overview->pp_marker_sun);
  overview->pp_layer_sun_rise_set = picplanner_draw_layer_new (overview->viewport);
  overview->pp_layer_sun = picplanner_draw_layer_new (overview->viewport);


  overview->pp_layer_center = picplanner_draw_layer_new (overview->viewport);

  shumate_simple_map_add_overlay_layer (overview->map, SHUMATE_LAYER (overview->pp_layer_milky_way_rise_set));
  shumate_simple_map_add_overlay_layer (overview->map, SHUMATE_LAYER (overview->pp_layer_moon_rise_set));
  shumate_simple_map_add_overlay_layer (overview->map, SHUMATE_LAYER (overview->pp_layer_sun_rise_set));
  shumate_simple_map_add_overlay_layer (overview->map, SHUMATE_LAYER (overview->pp_layer_milky_way));
  shumate_simple_map_add_overlay_layer (overview->map, SHUMATE_LAYER (overview->pp_layer_moon));
  shumate_simple_map_add_overlay_layer (overview->map, SHUMATE_LAYER (overview->pp_layer_sun));
  shumate_simple_map_add_overlay_layer (overview->map, SHUMATE_LAYER (overview->pp_layer_center));



  /*
   * Make all the bindings between widget properties and g_settings.
   */

  g_signal_connect (G_OBJECT (overview->viewport),
                    "notify::longitude",
                    G_CALLBACK (input_changed),
                    overview);
  g_signal_connect (G_OBJECT (overview->viewport),
                    "notify::latitude",
                    G_CALLBACK (input_changed),
                    overview);
  g_signal_connect (G_OBJECT (overview->settings),
                    "changed::longitude",
                    G_CALLBACK (input_changed),
                    overview);
  g_signal_connect (G_OBJECT (overview->settings),
                    "changed::latitude",
                    G_CALLBACK (input_changed),
                    overview);

  g_settings_bind (overview->settings, "map-fullscreen",
                   overview->basic_information, "visible",
                   G_SETTINGS_BIND_INVERT_BOOLEAN);

  g_settings_bind (overview->settings, "zoom-level",
                   overview->viewport, "zoom-level",
                   G_SETTINGS_BIND_DEFAULT);

  g_settings_bind (overview->settings, "sun-visible",
                   overview->switch_sun, "active",
                   G_SETTINGS_BIND_DEFAULT);

  g_settings_bind (overview->settings, "moon-visible",
                   overview->switch_moon, "active",
                   G_SETTINGS_BIND_DEFAULT);

  g_settings_bind (overview->settings, "milky-way-visible",
                   overview->switch_milky_way, "active",
                   G_SETTINGS_BIND_DEFAULT);

  /*
   * Connect the signals which recognize user input.
   * The user inputs are:
   * Changes of: north coordinate, east coordinate, hour, minute and a date change in the calendar.
   * The map is not treated seperately because the coordinates of the map are bound to the entry
   * values above.
   */

  g_signal_connect (G_OBJECT (overview->settings),
                    "changed::map-unit-metric",
                    G_CALLBACK (shumate_map_metric_imperial_scale),
                    overview);

  g_signal_connect (G_OBJECT (overview->settings),
                    "changed::map-unit-imperial",
                    G_CALLBACK (shumate_map_metric_imperial_scale),
                    overview);


  /*
   * Initialisation of values needed to detect when a user input ends
   */
  overview->input_new = true;
  overview->input_currently = false;
  overview->input_count = 0;
  overview->input_timeout_id = 0;

  input_changed (GTK_WIDGET (overview), NULL, overview);
}

static void
picplanner_overview_class_init (PicplannerOverviewClass *class)
{
  g_type_ensure (SHUMATE_TYPE_SIMPLE_MAP);

  gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
                                               "/de/zwarf/picplanner/window/overview-page/overview-view.ui");

  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, map);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, switch_sun);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, switch_moon);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, switch_milky_way);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_sun_rise);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_sun_set);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_moon_rise);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_moon_set);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_milky_way_rise);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_milky_way_set);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_elevation_sun);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_elevation_moon);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_elevation_milky_way);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_azimuth_sun);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_azimuth_moon);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, label_azimuth_milky_way);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PicplannerOverview, basic_information);
}

PicplannerOverview *
picplanner_overview_new ()
{
  return g_object_new (PICPLANNER_OVERVIEW_TYPE, NULL);
}
