#include <handler.h>

void hand_overview (GtkBuilder *builder, float latitude, float longitude, int *time_utc){
  GtkWidget *box;

  float coordinates_milkyway[2];
  float coordinates_sun[2];
  float coordinates_moon[2];

  box = GTK_WIDGET (gtk_builder_get_object (builder, "box_overview_plot"));
  gtk_container_foreach (GTK_CONTAINER (box), (GtkCallback) gtk_widget_destroy, NULL);

  hand_milky_way (latitude, longitude, time_utc, coordinates_milkyway);
  hand_sun (latitude, longitude, time_utc, coordinates_sun);
  hand_moon (latitude, longitude, time_utc, coordinates_moon);

  plot_overview (box);
  update_overview (coordinates_sun[0], coordinates_sun[1], coordinates_moon[0], coordinates_moon[1], coordinates_milkyway[0], coordinates_milkyway[1]);
}

void hand_update_overview (float latitude, float longitude, int *time_utc){
  float coordinates_milkyway[2];
  float coordinates_sun[2];
  float coordinates_moon[2];

  hand_milky_way (latitude, longitude, time_utc, coordinates_milkyway);
  hand_sun (latitude, longitude, time_utc, coordinates_sun);
  hand_moon (latitude, longitude, time_utc, coordinates_moon);

  update_overview (coordinates_sun[0], coordinates_sun[1], coordinates_moon[0], coordinates_moon[1], coordinates_milkyway[0], coordinates_milkyway[1]);
}

void hand_sun(float latitude, float longitude, int *time_utc, float *coordinates_sun_horizontal){
  /* g_print("Handler Sun\n"); */

  double time_jd_init;
  double *time_jd = &time_jd_init;

  double sidereal_time;
  float coordinates_sun[2];

  calc_jd (time_utc, time_jd);
  calc_coordinates_sun (*time_jd, coordinates_sun);
  calc_sidereal_time(longitude, time_jd, &sidereal_time);
  /*g_print("Sidereal Time: %f\n", sidereal_time);*/
  calc_convert_rotation_horizontal (*(coordinates_sun), *(coordinates_sun+1), latitude, sidereal_time, coordinates_sun_horizontal);
  /* g_print("Sun: Azimuth: %f, Elevation: %f\n", coordinates_sun_horizontal[0], coordinates_sun_horizontal[1]); */
}

void hand_moon(float latitude, float longitude, int *time_utc, float *coordinates_moon_horizontal){
  /* g_print("Handler Moon\n"); */

  double time_jd_init;
  double *time_jd = &time_jd_init;

  double sidereal_time;
  float coordinates_moon[2];

  calc_jd (time_utc, time_jd);
  calc_coordinates_moon (*time_jd, coordinates_moon);
  //g_print("Coordinates moon: %f, %f, Time: %f\n", coordinates_moon[0], coordinates_moon[1], *time_jd);

  calc_sidereal_time (longitude, time_jd, &sidereal_time);

  calc_convert_rotation_horizontal (coordinates_moon[0], coordinates_moon[1], latitude, sidereal_time, coordinates_moon_horizontal);
  //g_print("Moon: Azimuth: %f, Elevation: %f, time_jd: %f\n", coordinates_moon_horizontal[0], coordinates_moon_horizontal[1], *time_jd);
}

void hand_milky_way(float latitude, float longitude, int *time_utc, float *coordinates){
  /* g_print("Handler Milky Way\n"); */

  double time_jd_init;
  double *time_jd = &time_jd_init;

  double sidereal_time;

  float ra_milky_way = 266.417;
  float d_milky_way = -29.008;

  /* translate time to JD */
  calc_jd(time_utc, time_jd);
  /* calculate siderial time */
  calc_sidereal_time(longitude, time_jd, &sidereal_time);
  /* transfer rotating coordniate system to fixed coordniate system */
  calc_convert_rotation_horizontal(ra_milky_way, d_milky_way, latitude, sidereal_time, coordinates);
  /* g_print("Milky Way: Azimuth: %f, Elevation: %f\n", coordinates[0], coordinates[1]); */
}

void hand_plot_sun(GtkBuilder *builder, float latitude, float longitude, int *time_utc){
  GtkWidget *box;
  GtkLabel *label_time_culmination;
  GtkLabel *label_elevation;
  GtkLabel *label_sunrise;
  GtkLabel *label_dark_night_end;
  GtkLabel *label_blue_hour_morning;
  GtkLabel *label_golden_hour_morning;
  GtkLabel *label_sunset;
  GtkLabel *label_dark_night_begin;
  GtkLabel *label_blue_hour_evening;
  GtkLabel *label_golden_hour_evening;

  int time_dyn[6] = {*time_utc, *(time_utc+1), *(time_utc+2), *(time_utc+3), *(time_utc+4), -*(time_utc+5)};
  int time_dyn_local[6];
  int time_max_elevation[2]={-90,0};
  int time_sunrise[2]={-1,0};
  int time_sunset[2]={-1,0};
  int time_blue_morning[2];
  int time_gold_morning_begin[2];
  int time_gold_morning_end[2];
  int time_blue_evening[2];
  int time_gold_evening_begin[2];
  int time_gold_evening_end[2];
  int time_dark_night_end[2];
  int time_dark_night_begin[2];

  float azimuth[290], elevation[290];
  float result[2];
  float elevation_last;
  float min_elevation, max_elevation;
  float azimuth_max, azimuth_sunrise, azimuth_sunset;

  char c_time_culmination[16];
  char c_elevation_culmination[7];
  char c_time_sunrise[16];
  char c_time_sunset[16];
  char c_time_blue_morning[15];
  char c_time_gold_morning[15];
  char c_time_blue_evening[15];
  char c_time_gold_evening[15];
  char c_time_dark_night_end[6];
  char c_time_dark_night_begin[6];

  for (int i = 0; i<1440; i++){
    time_dyn[3]=(int)(i/60);
    time_dyn[4]=i-(int)(i/60)*60;
    utc_zone_to_time (time_dyn, time_dyn_local);

    hand_sun (latitude, longitude, time_dyn_local, result);

    if (i%5==0){
      azimuth[i/5+2] = result[0];
      elevation[i/5+2] = result[1];
    }

    if (i==0){
      min_elevation = result[1];
      max_elevation = result[1];
      elevation_last = result[1];
    }
    else{
      if (result[1]<min_elevation){
        min_elevation = result[1];
      }
      if (result[1]>max_elevation){
        max_elevation = result[1];
        azimuth_max = result[0];
        time_max_elevation[0]=time_dyn[3];
        time_max_elevation[1]=time_dyn[4];
      }
      if (result[1]>0 && elevation_last<0){
        azimuth_sunrise=result[0];
        time_sunrise[0]=time_dyn[3];
        time_sunrise[1]=time_dyn[4];
      }
      if (result[1]<0 && elevation_last>0){
        azimuth_sunset=result[0];
        time_sunset[0]=time_dyn[3];
        time_sunset[1]=time_dyn[4];
      }
      if (result[1]>-18 && elevation_last<-18){
        time_dark_night_end[0] = time_dyn[3];
        time_dark_night_end[1] = time_dyn[4];
      }
      if (result[1]>-8 && elevation_last<-8){
        time_blue_morning[0] = time_dyn[3];
        time_blue_morning[1] = time_dyn[4];
      }
      if (result[1]>-4 && elevation_last<-4){
        time_gold_morning_begin[0] = time_dyn[3];
        time_gold_morning_begin[1] = time_dyn[4];
      }
      if (result[1]>6 && elevation_last<6){
        time_gold_morning_end[0] = time_dyn[3];
        time_gold_morning_end[1] = time_dyn[4];
      }
      if (result[1]<-18 && elevation_last>-18){
        time_dark_night_begin[0] = time_dyn[3];
        time_dark_night_begin[1] = time_dyn[4];
      }
      if (result[1]<-8 && elevation_last>-8){
        time_blue_evening[0] = time_dyn[3];
        time_blue_evening[1] = time_dyn[4];
      }
      if (result[1]<6 && elevation_last>6){
        time_gold_evening_begin[0] = time_dyn[3];
        time_gold_evening_begin[1] = time_dyn[4];
      }
      if (result[1]<-4 && elevation_last>-4){
        time_gold_evening_end[0] = time_dyn[3];
        time_gold_evening_end[1] = time_dyn[4];
      }

      elevation_last = result[1];
    }
  }
  /* g_print("Time max elevation: %02d:%02d, Time sunrise: %02d:%02d, Time sunset: %02d:%02d\n",
          time_max_elevation[0],time_max_elevation[1],time_sunrise[0],time_sunrise[1],time_sunset[0],time_sunset[1]); */



  elevation[0] = min_elevation;
  elevation[1] = max_elevation;

  box = GTK_WIDGET (gtk_builder_get_object (builder, "box_sun_elevation_plot"));
  label_time_culmination = GTK_LABEL (gtk_builder_get_object (builder, "sun_time_culmination"));
  label_elevation = GTK_LABEL (gtk_builder_get_object (builder, "sun_elevation"));
  label_sunrise = GTK_LABEL (gtk_builder_get_object (builder, "sunrise"));
  label_dark_night_end = GTK_LABEL (gtk_builder_get_object (builder, "dark_night_end"));
  label_blue_hour_morning = GTK_LABEL (gtk_builder_get_object (builder, "morning_bh"));
  label_golden_hour_morning = GTK_LABEL (gtk_builder_get_object (builder, "morning_gh"));
  label_sunset = GTK_LABEL (gtk_builder_get_object (builder, "sunset"));
  label_dark_night_begin = GTK_LABEL (gtk_builder_get_object (builder, "dark_night_begin"));
  label_blue_hour_evening = GTK_LABEL (gtk_builder_get_object (builder, "evening_bh"));
  label_golden_hour_evening = GTK_LABEL (gtk_builder_get_object (builder, "evening_gh"));

  gtk_container_foreach (GTK_CONTAINER (box), (GtkCallback) gtk_widget_destroy, NULL);
  plot_elevation_sun (elevation, box);
  course_sun_overview (azimuth, elevation);

  sprintf (c_time_culmination, "%02d:%02d (@ %.1f\u00B0)", time_max_elevation[0], time_max_elevation[1], azimuth_max);
  gtk_label_set_text (label_time_culmination, c_time_culmination);

  sprintf (c_elevation_culmination, "%.1f\u00B0", max_elevation);
  gtk_label_set_text (label_elevation, c_elevation_culmination);

  sprintf (c_time_sunrise, "%02d:%02d (@ %.1f\u00B0)", time_sunrise[0], time_sunrise[1], azimuth_sunrise);
  gtk_label_set_text (label_sunrise, c_time_sunrise);

  sprintf (c_time_sunset, "%02d:%02d (@ %.1f\u00B0)", time_sunset[0], time_sunset[1], azimuth_sunset);
  gtk_label_set_text (label_sunset, c_time_sunset);

  sprintf (c_time_blue_morning, "%02d:%02d - %02d:%02d",
           time_blue_morning[0],time_blue_morning[1], time_gold_morning_begin[0],time_gold_morning_begin[1]);
  gtk_label_set_text (label_blue_hour_morning, c_time_blue_morning);

  sprintf (c_time_gold_morning, "%02d:%02d - %02d:%02d",
          time_gold_morning_begin[0],time_gold_morning_begin[1],time_gold_morning_end[0],time_gold_morning_end[1]);
  gtk_label_set_text (label_golden_hour_morning, c_time_gold_morning);

  sprintf (c_time_dark_night_end, "%02d:%02d", time_dark_night_end[0], time_dark_night_end[1]);
  gtk_label_set_text (label_dark_night_end, c_time_dark_night_end);

  sprintf (c_time_blue_evening, "%02d:%02d - %02d:%02d",
           time_gold_evening_end[0],time_gold_evening_end[1], time_blue_evening[0],time_blue_evening[1]);
  gtk_label_set_text (label_blue_hour_evening, c_time_blue_evening);

  sprintf (c_time_gold_evening, "%02d:%02d - %02d:%02d",
          time_gold_evening_begin[0],time_gold_evening_begin[1],time_gold_evening_end[0],time_gold_evening_end[1]);
  gtk_label_set_text (label_golden_hour_evening, c_time_gold_evening);

  sprintf (c_time_dark_night_begin, "%02d:%02d", time_dark_night_begin[0], time_dark_night_begin[1]);
  gtk_label_set_text (label_dark_night_begin, c_time_dark_night_begin);
}

void hand_plot_moon(GtkBuilder *builder, float latitude, float longitude, int *time_utc){
  GtkWidget *box;
  int time_dyn[6] = {*time_utc, *(time_utc+1), *(time_utc+2), *(time_utc+3), *(time_utc+4), -*(time_utc+5)};
  int time_dyn_local[6];
  float azimuth[290], elevation[290];
  float result[2];
  float min_elevation, max_elevation;
  float elevation_last;
  float azimuth_max;
  int time_max_elevation[2];
  float azimuth_rise;
  float azimuth_set;
  int time_rise[2];
  int time_set[2];

  char c_time_culmination[16];
  char c_elevation[7];
  char c_time_rise[16];
  char c_time_set[16];

  GtkLabel *label_time_culmination;
  GtkLabel *label_elevation;
  GtkLabel *label_rise;
  GtkLabel *label_set;

  for (int i = 0; i<1440; i++){
    *(time_dyn+3)=(int)(i/60);
    *(time_dyn+4)=i-(int)(i/60)*60;
    utc_zone_to_time (time_dyn, time_dyn_local);

    hand_moon (latitude, longitude, time_dyn_local, result);

    if (i%5==0){
      azimuth[i/5+2] = result[0];
      elevation[i/5+2] = result[1];
    }

    if (i==0){
      min_elevation = result[1];
      max_elevation = result[1];
    }
    else{
      if (result[1]<min_elevation){
        min_elevation = result[1];
      }
      if (result[1]>max_elevation){
        max_elevation = result[1];
        azimuth_max = result[0];
        time_max_elevation[0]=time_dyn[3];
        time_max_elevation[1]=time_dyn[4];
      }
      if (result[1]>0 && elevation_last<0){
        azimuth_rise=result[0];
        time_rise[0]=time_dyn[3];
        time_rise[1]=time_dyn[4];
      }
      if (result[1]<0 && elevation_last>0){
        azimuth_set=result[0];
        time_set[0]=time_dyn[3];
        time_set[1]=time_dyn[4];
      }
    }
    elevation_last = result[1];
  }

  elevation[0] = min_elevation;
  elevation[1] = max_elevation;

  box = GTK_WIDGET (gtk_builder_get_object(builder, "box_moon_elevation_plot"));
  gtk_container_foreach (GTK_CONTAINER (box), (GtkCallback) gtk_widget_destroy, NULL);
  plot_elevation_moon (elevation, box);
  course_moon_overview (azimuth, elevation);

  label_rise = GTK_LABEL (gtk_builder_get_object (builder, "moon_rise"));
  label_set = GTK_LABEL (gtk_builder_get_object (builder, "moon_set"));
  label_time_culmination = GTK_LABEL (gtk_builder_get_object (builder, "moon_time_culmination"));
  label_elevation = GTK_LABEL (gtk_builder_get_object (builder, "moon_elevation"));

  sprintf (c_time_culmination, "%02d:%02d (@%.1f\u00B0)", time_max_elevation[0], time_max_elevation[1], azimuth_max);
  gtk_label_set_text (label_time_culmination, c_time_culmination);

  sprintf (c_elevation, "%.1f\u00B0", max_elevation);
  gtk_label_set_text (label_elevation, c_elevation);

  sprintf (c_time_rise, "%02d:%02d (@ %.1f\u00B0)", time_rise[0], time_rise[1], azimuth_rise);
  gtk_label_set_text (label_rise, c_time_rise);

  sprintf (c_time_set, "%02d:%02d (@ %.1f\u00B0)", time_set[0], time_set[1], azimuth_set);
  gtk_label_set_text (label_set, c_time_set);
}


void hand_plot_mw(GtkBuilder *builder, float latitude, float longitude, int *time_utc){
  GtkWidget *box;
  int time_dyn[6] = {*time_utc, *(time_utc+1), *(time_utc+2), *(time_utc+3), *(time_utc+4), -*(time_utc+5)};
  int time_dyn_local[6];
  float azimuth[290], elevation[290];
  float result[2];
  float min_elevation, max_elevation;
  float elevation_last;
  float azimuth_max;
  int time_max_elevation[2];
  float azimuth_rise;
  float azimuth_set;
  int time_rise[2];
  int time_set[2];

  char c_time_culmination[16];
  char c_elevation[7];
  char c_time_rise[16];
  char c_time_set[16];

  GtkLabel *label_time_culmination;
  GtkLabel *label_elevation;
  GtkLabel *label_rise;
  GtkLabel *label_set;

  for (int i = 0; i<1440; i++){
    *(time_dyn+3)=(int)(i/60);
    *(time_dyn+4)=i-(int)(i/60)*60;
    utc_zone_to_time (time_dyn, time_dyn_local);

    hand_milky_way (latitude, longitude, time_dyn_local, result);

    if (i%5==0){
      azimuth[i/5+2] = result[0];
      elevation[i/5+2] = result[1];
    }

    if (i==0){
      min_elevation = result[1];
      max_elevation = result[1];
    }
    else{
      if (result[1]<min_elevation){
        min_elevation = result[1];
      }
      if (result[1]>max_elevation){
        max_elevation = result[1];
        azimuth_max = result[0];
        time_max_elevation[0]=time_dyn[3];
        time_max_elevation[1]=time_dyn[4];
      }
      if (result[1]>0 && elevation_last<0){
        azimuth_rise=result[0];
        time_rise[0]=time_dyn[3];
        time_rise[1]=time_dyn[4];
      }
      if (result[1]<0 && elevation_last>0){
        azimuth_set=result[0];
        time_set[0]=time_dyn[3];
        time_set[1]=time_dyn[4];
      }
    }
    elevation_last = result[1];
  }

  elevation[0] = min_elevation;
  elevation[1] = max_elevation;

  box = GTK_WIDGET (gtk_builder_get_object(builder, "box_mw_elevation_plot"));
  gtk_container_foreach (GTK_CONTAINER (box), (GtkCallback) gtk_widget_destroy, NULL);
  plot_elevation_mw (elevation, box);
  course_mw_overview (azimuth, elevation);

  label_rise = GTK_LABEL (gtk_builder_get_object (builder, "mw_rise"));
  label_set = GTK_LABEL (gtk_builder_get_object (builder, "mw_set"));
  label_time_culmination = GTK_LABEL (gtk_builder_get_object (builder, "mw_time_culmination"));
  label_elevation = GTK_LABEL (gtk_builder_get_object (builder, "mw_elevation"));

  sprintf (c_time_culmination, "%02d:%02d (@%.1f\u00B0)", time_max_elevation[0], time_max_elevation[1], azimuth_max);
  gtk_label_set_text (label_time_culmination, c_time_culmination);

  sprintf (c_elevation, "%.1f\u00B0", max_elevation);
  gtk_label_set_text (label_elevation, c_elevation);

  sprintf (c_time_rise, "%02d:%02d (@ %.1f\u00B0)", time_rise[0], time_rise[1], azimuth_rise);
  gtk_label_set_text (label_rise, c_time_rise);

  sprintf (c_time_set, "%02d:%02d (@ %.1f\u00B0)", time_set[0], time_set[1], azimuth_set);
  gtk_label_set_text (label_set, c_time_set);
}
