/*
 * time-picker.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 "time-picker.h"

struct _TimePicker
{
  GtkBox parent_instance;

  /* Time and date selector */
  GtkWidget           *label_time_zone;

  GtkWidget           *calendar;
  GtkWidget           *calendar_popover;
  GtkWidget           *calendar_button;

  GtkWidget           *spin_button_hour;
  GtkWidget           *spin_button_minute;
};

G_DEFINE_TYPE (TimePicker, time_picker, GTK_TYPE_BOX)

static guint signal_change;

void
time_picker_set_date_time (TimePicker *time_picker,
                           GDateTime *date_time)
{
  gtk_calendar_select_day   (GTK_CALENDAR (time_picker->calendar),
                             date_time);
  gtk_spin_button_set_value (GTK_SPIN_BUTTON (time_picker->spin_button_hour),
                             g_date_time_get_hour (date_time));
  gtk_spin_button_set_value (GTK_SPIN_BUTTON (time_picker->spin_button_minute),
                             g_date_time_get_minute (date_time));
}

void
time_picker_set_time_zone (TimePicker *time_picker,
                           double      time_zone)
{
  char *char_time_zone;
  char_time_zone = g_strdup_printf ("UTC %s%.1f", time_zone>=0 ? "+" : "", time_zone);
  gtk_label_set_text (GTK_LABEL (time_picker->label_time_zone), char_time_zone);
  g_free (char_time_zone);
}


int
time_picker_get_year (TimePicker *time_picker)
{
  int year;
  GDateTime *date_selected;

  date_selected = gtk_calendar_get_date (GTK_CALENDAR (time_picker->calendar));
  year = g_date_time_get_year (date_selected);

  g_date_time_unref (date_selected);
  return year;
}

int
time_picker_get_month (TimePicker *time_picker)
{
  int month;
  GDateTime *date_selected;

  date_selected = gtk_calendar_get_date (GTK_CALENDAR (time_picker->calendar));
  month = g_date_time_get_month (date_selected);

  g_date_time_unref (date_selected);
  return month;
}

int
time_picker_get_day (TimePicker *time_picker)
{
  int day;
  GDateTime *date_selected;

  date_selected = gtk_calendar_get_date (GTK_CALENDAR (time_picker->calendar));
  day = g_date_time_get_day_of_month (date_selected);

  g_date_time_unref (date_selected);
  return day;
}

int
time_picker_get_hour (TimePicker *time_picker)
{
  int hour;
  hour = gtk_spin_button_get_value (GTK_SPIN_BUTTON (time_picker->spin_button_hour));
  return hour;
}

int
time_picker_get_minute (TimePicker *time_picker)
{
  int minute;
  minute = gtk_spin_button_get_value (GTK_SPIN_BUTTON (time_picker->spin_button_minute));
  return minute;
}

static void
input_changed (GtkWidget  *self,
               TimePicker *time_picker)
{
  (void) self;

  g_signal_emit (time_picker,
                 signal_change,
                 0, NULL);
}


/*
 * Change the text of the GtkSpinButton to always be a two digit number.
 * E.g. don't show one o'clock AM as 1:0 but show 01:00
 */
static gboolean
time_spin_button_text (GtkSpinButton *self)
{
  int value;
  char *button_text;
  GtkAdjustment *adjustment;

  adjustment = gtk_spin_button_get_adjustment (self);
  value = (int) gtk_adjustment_get_value (adjustment);
  button_text = g_strdup_printf ("%02d", value);
  gtk_editable_set_text (GTK_EDITABLE (self),
                         button_text);
  g_free (button_text);

  return TRUE;
}

/*
 * Change the text of the button which presents the calender after a date was selected.
 * Furthermore the behavior of the popup is controlled.
 */
static void
day_selected (GtkCalendar         *self,
              TimePicker          *time_picker)
{
  (void) self;
  GDateTime *date_selected;
  GtkPopover *popover;
  char *button_text;

  date_selected = gtk_calendar_get_date (GTK_CALENDAR (time_picker->calendar));

  /*
   * Set text of the button to the selected date
   */
  button_text = g_strdup_printf ("%d.%d.%d",
                                 g_date_time_get_day_of_month (date_selected),
                                 g_date_time_get_month (date_selected),
                                 g_date_time_get_year (date_selected));
  gtk_menu_button_set_label (GTK_MENU_BUTTON (time_picker->calendar_button),
                             button_text);

  /*
   * Close Popover after the day was selected
   * TODO: Popdown happens automatically if a month is chosen which has less days then
   * the day number previously selected.
   */
  popover = GTK_POPOVER(time_picker->calendar_popover);
  gtk_popover_popdown (popover);

  g_free (button_text);
  g_date_time_unref (date_selected);

  input_changed (GTK_WIDGET (self), time_picker);
}

static void
time_picker_init (TimePicker *time_picker)
{
  gtk_widget_init_template (GTK_WIDGET (time_picker));

  g_signal_connect (G_OBJECT (time_picker->spin_button_hour),
                    "value-changed",
                    G_CALLBACK (input_changed),
                    time_picker);

  g_signal_connect (G_OBJECT (time_picker->spin_button_minute),
                    "value-changed",
                    G_CALLBACK (input_changed),
                    time_picker);

  g_signal_connect (G_OBJECT (time_picker->calendar),
                    "day-selected",
                    G_CALLBACK (day_selected),
                    time_picker);
}

static void
time_picker_class_init (TimePickerClass *class)
{
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
  gtk_widget_class_set_template_from_resource (widget_class,
                                               "/de/zwarf/picplanner/time-picker/time-picker.ui");
  gtk_widget_class_bind_template_child (widget_class, TimePicker, label_time_zone);
  gtk_widget_class_bind_template_child (widget_class, TimePicker, calendar);
  gtk_widget_class_bind_template_child (widget_class, TimePicker, calendar_popover);
  gtk_widget_class_bind_template_child (widget_class, TimePicker, calendar_button);
  gtk_widget_class_bind_template_child (widget_class, TimePicker, spin_button_hour);
  gtk_widget_class_bind_template_child (widget_class, TimePicker, spin_button_minute);

  gtk_widget_class_bind_template_callback (widget_class, day_selected);
  gtk_widget_class_bind_template_callback (widget_class, time_spin_button_text);

  signal_change = g_signal_new ("date_time_changed",
                                G_OBJECT_CLASS_TYPE (class),
                                G_SIGNAL_RUN_LAST,
                                0, NULL, NULL, NULL,
                                G_TYPE_NONE,
                                0);
}

TimePicker *
time_picker_new ()
{
  return g_object_new (TIME_PICKER_TYPE, NULL);
}