/***************************************************************************************
 *
 * histogram.cc is part of SimpleSkyCam.
 *
 *****************************************************************************************/

#include <math.h>

#include "simpleskycam.h"
#include "histogram.h"
#include "gui.h"
#include "configuration.h"
#include "video.h"

#define HISTOGRAM_WIDTH 256
#define HISTOGRAM_MARGIN 16

GtkWidget *histogram_da = NULL;
int histogram[3][HISTOGRAM_WIDTH];	// 6* hist_width min, max, min , max.....
int histogram_max;				// max vlaue
int histogram_zoom_start = 0;           // first zoom value
int histogram_zoom_stop = HISTOGRAM_WIDTH-1; // second zoom value
int histogram_x;                        // current mouse x-coordinate 
int histogram_pressed_x;                // window x-coordinate when pressing a button
int histogram_released_x;               // window x-coordinate when releasing a button
int histogram_pressed = 0;              // indicates button pressed or not
int histogram_zoomed = 0;               // indicates zoom

extern GtkBuilder *_builder_;			// work around for threads

void cb_histogramda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data) {
  int clientw, clienth, px, px2, py2;
	GdkRGBA color;
	char txt[255];

	if (histogram_da == NULL) // should only be called once
		histogram_da = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "histogram-da"));
	clienth = gtk_widget_get_allocated_height(histogram_da);
	clientw = gtk_widget_get_allocated_width(histogram_da);

	//
	// put the drawing area on the screen
    cairo_paint(cr);
    cairo_fill (cr);

    if (histogram_max == 0) return;

    for (int chan = 0; chan < 3; chan++) {
		switch (chan) {
		case 0:
			color.blue = 0.0;
			color.red = 1.0;
			color.green = 0.0;
			color.alpha = 0.5;
			break;
		case 1:
			color.blue = 0.0;
			color.red = 0.0;
			color.green = 1.0;
			color.alpha = 0.5;
			break;
		case 2:
			color.blue = 1.0;
			color.red = 0.0;
			color.green = 0.0;
			color.alpha = 0.5;
			break;
		}
		gdk_cairo_set_source_rgba(cr, &color);

		int histogram_width = histogram_zoom_stop - histogram_zoom_start + 1;
		int histogram_scale = histogram_width - 1 > 0 ? histogram_width - 1 : 1;
    	for (int i = 0; i < histogram_width; i++) {
	  px = HISTOGRAM_MARGIN + ((clientw-HISTOGRAM_MARGIN*2) * i) / histogram_scale;
	  if (config.GetHistogramLog())
	    py2 = (clienth-HISTOGRAM_MARGIN) - ((clienth-HISTOGRAM_MARGIN*2) * log10(histogram[chan][histogram_zoom_start+i]+1) / log10(histogram_max));
	  else
	    py2 = (clienth-HISTOGRAM_MARGIN) - ((clienth-HISTOGRAM_MARGIN*2) * histogram[chan][histogram_zoom_start+i] / histogram_max);

    		if (i == 0) cairo_move_to(cr, px, py2);
    		else 		cairo_line_to(cr, px, py2);

    	}
		cairo_stroke(cr);

		if (histogram_pressed) {
		  if (histogram_pressed_x < histogram_x) {
		    px = histogram_pressed_x;
		    px2 = histogram_x;
		  } else {
		    px2 = histogram_pressed_x;
		    px = histogram_x;
		  }
		  cairo_set_source_rgba(cr, 0.5, 0.5, 0.5, 0.5);
		  cairo_rectangle (cr, px, 0, px2-px, clienth);
		  cairo_fill (cr);
		}
    }

	// draw some text
    if (config.GetHistogramLog())    snprintf (txt, 255, "%d - Log", histogram_max);
    else					     snprintf (txt, 255, "%d - Lin", histogram_max);

	for (int i = 0; i < 5; i++) {
		int dx, dy;

		switch (i) {
		case 0:
			cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
			dx = -1;
			dy = 0;
			break;
		case 1:
			dx = +1;
			dy = 0;
			break;
		case 2:
			dx = 0;
			dy = -1;
			break;
		case 3:
			dx = 0;
			dy = +1;
			break;
		case 4:
			cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
			dx = 0;
			dy = 0;
			break;
		}

		cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
		cairo_set_font_size (cr, 12);
		cairo_move_to (cr, 10+dx, 15+dy);
		cairo_show_text(cr, txt);
		cairo_stroke(cr);
	}
};


/*
 * test function
 */
void histogram_update(VideoFrame *vf) {

	// save some time
	static int to = 0;
	if ((++to) % 8 == 0) return;

	int chan, i, x, y;

	if (vf == NULL) return;
	if (vf->w <= 0 ) return;

	// initialize histogram
	memset (histogram, 0, sizeof(histogram));

	for (i = 0, x = 0; x < vf->w; x++) {
		for (y = 0; y < vf->h; y++) {
			for (chan = 0; chan < 3; chan++) {
				histogram[chan][vf->data[i++]]++;
			}
		}
	}

	if (histogram_da)
		gdk_window_invalidate_rect(gtk_widget_get_window(histogram_da), NULL, true);

	for (histogram_max = 0, chan = 0; chan < 3; chan++) for (i = 0; i < HISTOGRAM_WIDTH; i++)
		if (histogram_max < histogram[chan][i]) histogram_max = histogram[chan][i];
};



void cb_histogramda_motion (GtkWidget *widget, GdkEvent *event, gpointer data) {
  if(!histogram_zoomed) {
    histogram_x = (int)round(event->button.x);
  }
};


void cb_histogramda_btnpress (GtkWidget *widget, gpointer data) {
  if (!histogram_zoomed) {
    if (!histogram_pressed) {
      histogram_pressed = 1;
      histogram_pressed_x = histogram_x;
    }
  } else {
    histogram_zoomed = 0;
    histogram_zoom_start = 0;
    histogram_zoom_stop = HISTOGRAM_WIDTH-1;
  }
};


void cb_histogramda_btnrelease (GtkWidget *widget, gpointer data) {
  if (!histogram_zoomed) {
    if (histogram_pressed) {
      histogram_pressed = 0;
      histogram_released_x = histogram_x;
      histogram_zoomed = 1;

      // here we need to compute start/stop coordinates inside histogram
      int clientw;
      clientw = gtk_widget_get_allocated_width(histogram_da);

      // translate first coordinate
      histogram_zoom_start = (histogram_pressed_x - HISTOGRAM_MARGIN) * HISTOGRAM_WIDTH / (clientw - HISTOGRAM_MARGIN*2);
      if (histogram_zoom_start < 0) histogram_zoom_start = 0;
      if (histogram_zoom_start >= HISTOGRAM_WIDTH) histogram_zoom_start = HISTOGRAM_WIDTH-1;

      // translate second coordinate
      histogram_zoom_stop = (histogram_released_x - HISTOGRAM_MARGIN) * HISTOGRAM_WIDTH / (clientw - HISTOGRAM_MARGIN*2) + 1;
      // limit the values
      if (histogram_zoom_stop < 0) histogram_zoom_stop = 0;
      if (histogram_zoom_stop >= HISTOGRAM_WIDTH) histogram_zoom_stop = HISTOGRAM_WIDTH-1;

      // exchange the values if necessary
      if (histogram_zoom_start > histogram_zoom_stop) {
	int t = histogram_zoom_start;
	histogram_zoom_start = histogram_zoom_stop;
	histogram_zoom_stop = t;
      }
    }
  }
};


void cb_histogramda_keypress (GtkWidget *widget, GdkEventKey *event, gpointer data) {
	printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);

	if (event == NULL) return;

	else if (event->keyval == 'l') config.SetHistogramLog(config.GetHistogramLog() == 0);
};


void cb_histogram_show_window (GtkWidget *widget, gpointer data) {
	printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);

	GtkWidget *wnd = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "window-histogram"));
	gtk_widget_show(wnd);
};


void cb_menu_set_histlog (GtkCheckMenuItem *checkmenuitem,  gpointer user_data) {
	config.SetHistogramLog(gtk_check_menu_item_get_active(checkmenuitem) == TRUE);
}




