

#include <gst/gst.h>
#include <gtk/gtk.h>
#include <gst/video/videooverlay.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h> // includes GDK_q

GstElement *pipeline;

gboolean handle_bus_msg(GstMessage * message, GtkWidget *window)
{


		GstVideoOverlay *video_overlay;

		// ignore anything but 'prepare-xwindow-id' element messages
		if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
				return FALSE;
 
//     if (!gst_structure_has_name(message->structure, "prepare-xwindow-id"))
//     if (!gst_structure_has_name(gst_message_get_structure (message), "prepare-xwindow-id"))
		if (! gst_is_video_overlay_prepare_window_handle_message (message))
				return FALSE;
 
		g_print("Got prepare-xwindow-id msg\n");
		// FIXME: see https://bugzilla.gnome.org/show_bug.cgi?id=599885
//     gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(message)), GDK_WINDOW_XWINDOW(window->window));
//     gst_x_overlay_set_xwindow_handle(GST_X_OVERLAY(GST_MESSAGE_SRC(message)), GDK_WINDOW_XID(window->window));

// 		video_overlay = GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message));
// 		gst_video_overlay_set_window_handle (video_overlay, GDK_WINDOW_XID(window->window));
		gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)), GDK_WINDOW_XID(window->window));

//   /* Retrieve window handler from GDK */
// #if defined (GDK_WINDOWING_WIN32)
//   window_handle = (guintptr)GDK_WINDOW_HWND (window);
// #elif defined (GDK_WINDOWING_QUARTZ)
//   window_handle = gdk_quartz_window_get_nsview (window);
// #elif defined (GDK_WINDOWING_X11)
//   window_handle = GDK_WINDOW_XID (window);
// #endif
//   /* Pass it to playbin2, which implements XOverlay and will forward it to the video sink */
//   gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->playbin2), window_handle);

//     return TRUE;
}

gboolean bus_call(GstBus * bus, GstMessage *msg, gpointer data)
{
		GtkWidget *window = (GtkWidget*) data;
		switch(GST_MESSAGE_TYPE(msg))
		{
				case GST_MESSAGE_ELEMENT:
						handle_bus_msg(msg, window);
						break;

				default:
						break;
		}

		return TRUE;
}

static void make_window_black(GtkWidget *window)
{
		GdkColor color;
		gdk_color_parse("black", &color);
		gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color);
}

char * hms_from_secs(gint64 nsecs)
{
	gint64 secondsIn;
	int seconds, minutes, hours;
	char hms[20];

	secondsIn = nsecs/1e9;

	hours     = secondsIn / 3600 ;
	minutes	  = secondsIn % (hours*3600) / 60 ;
	seconds   = secondsIn % (hours*3600) % 60 ;
 
// 	Seconds   = InSeconds % 60 ;
// 	InMinutes = InSeconds / 60 ;
// 
// 	Minutes   = InMinutes % 60 ;
// 	InHours   = InMinutes / 60 ;


// 	Days      = InHours / 24 ;

	sprintf(hms, "%d:%d:%d", hours, minutes, seconds);
	printf("%s\n", hms); 

// 	return hms;

// 	int test;
// 	test = 20 % 3;
// 	printf("test: %d\n", hours);
}

static gboolean key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
{

	switch (event->keyval)
	{
		case GDK_KEY_f:
		{
				gboolean is_fullscreen = (gdk_window_get_state(GDK_WINDOW(widget->window)) == GDK_WINDOW_STATE_FULLSCREEN);

				if (is_fullscreen) 
					gtk_window_unfullscreen(GTK_WINDOW(widget));
				else
					gtk_window_fullscreen(GTK_WINDOW(widget));

		}

		break;

		case GDK_KEY_p:
		{

// 				gboolean is_playing = (gdk_window_get_state(GDK_WINDOW(widget->window)) == GDK_WINDOW_STATE_FULLSCREEN);
// 
// 				if (is_fullscreen) 
// 					gtk_window_unfullscreen(GTK_WINDOW(widget));
// 				else
// 					gtk_window_fullscreen(GTK_WINDOW(widget));

// /* This function is called when the PLAY button is clicked */
// static void play_cb () 
// {
// 	gst_element_set_state (pipeline, GST_STATE_PLAYING);
// }
// 	 
// /* This function is called when the PAUSE button is clicked */
// static void pause_cb ()
// {
// 	gst_element_set_state (pipeline, GST_STATE_PAUSED);
// }
// 	 
// /* This function is called when the STOP button is clicked */
// static void stop_cb ()
// {
// 	gst_element_set_state (pipeline, GST_STATE_READY);
// }


		}

		break;

		case GDK_KEY_Right:
		{

// 			gint64 *pos_ns_ptr, *dur_ns_ptr;
			gint64 dur_ns, pos_ns, seek_ns;
			GstFormat format;
		
			format = GST_FORMAT_TIME;

// 	// 		gst_element_query_duration(pipeline,&format,&dur_ns);

			if ( !gst_element_query_position(pipeline,format,&pos_ns) )
				g_print("query position failed\n");

// 			g_print ("Before Seek Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (pos_ns_ptr), GST_TIME_ARGS (dur_ns_ptr));
// 
// 			pos_ns_int = (gint64) pos_ns_ptr;
// 			dur_ns_int = (gint64) dur_ns_ptr;
// 
// 	// 		printf("position: %ld / %ld\n",position,duration);
// 	// 		hms_from_secs(duration);
// 
			seek_ns = pos_ns + 2*GST_SECOND;
			g_print ("pos_ns: %li, seek_ns: %li\n",pos_ns,seek_ns);
			g_print ("position: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (seek_ns));
// 			hms_from_secs(seek_ns_int);
// 			g_print ("position: %s\n",hms_from_secs(seek_ns_int));

// 	// 		gst_element_seek_simple(pipeline, format, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, seek_ns);
// 	// 
// 	// 		gst_element_query_position(pipeline,&format,&pos_ns);
// 	// 		g_print ("After Seek Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (pos_ns), GST_TIME_ARGS (dur_ns));
// 	// 		printf("\n");
// 
// // gboolean            gst_element_seek_simple             (GstElement *element,
// //                                                          GstFormat format,
// //                                                          GstSeekFlags seek_flags,
// //                                                          gint64 seek_pos);
// // gboolean            gst_element_seek                    (GstElement *element,
// //                                                          gdouble rate,
// //                                                          GstFormat format,
// //                                                          GstSeekFlags flags,
// //                                                          GstSeekType start_type,
// //                                                          gint64 start,
// //                                                          GstSeekType stop_type,
// //                                                          gint64 stop);
// 
// 			gst_element_seek_simple (pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,	seek_ns_int);
// 
// 

			if ( !gst_element_seek_simple (pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,	seek_ns) ) 
			{

				g_print ("Seek failed!\n");

			}

// 			if (!gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
// 					 GST_SEEK_TYPE_SET, seek_ns_int,
// 					 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) 
// 			{
// 
// 				g_print ("Seek failed!\n");
// 
// 			}
// 	
// 			return TRUE;

		}

		break;



		default:
			return FALSE;
 
	}

	return FALSE; 
}

//     if (event->keyval != 'f')
//         return TRUE;
//     else 
//         g_print("Toggling fullscreen\n");
// 
//     gboolean is_fullscreen = (gdk_window_get_state(GDK_WINDOW(widget->window)) == GDK_WINDOW_STATE_FULLSCREEN);
// 
//     if (is_fullscreen) 
//         gtk_window_unfullscreen(GTK_WINDOW(widget));
//     else
//         gtk_window_fullscreen(GTK_WINDOW(widget));
// 
//     return TRUE;
// }

void destroy_cb(GtkWidget * widget, gpointer data)
{
		GMainLoop *loop = (GMainLoop*) data;
		g_print("Window destroyed\n");
		g_main_loop_quit(loop);
}

gint main (gint argc, gchar *argv[])
{
		GstStateChangeReturn ret;

		GMainLoop *loop;
		GtkWidget *window;
		GError *error = NULL;

		/* initialization */
		gst_init(&argc, &argv);
		gtk_init(&argc, &argv);

		loop = g_main_loop_new(NULL, FALSE);

		/* build window and attach expose event to expose callback */
		window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

		/* create elements */
//     pipeline = gst_pipeline_new("my_pipeline");
//     pipeline = gst_parse_launch("filesrc location=/home/jalips/data/mytv/recordings/EP00753796.0160_1357005474.67.mpg ! decodebin name=decoder decoder. ! queue ! audioconvert ! alsasink device-name=\"CONEXANT Analog\" decoder. ! deinterlace ! ffmpegcolorspace ! glimagesink",&error);
// 		pipeline = gst_parse_launch("filesrc location=/home/jalips/data/mytv/recordings/EP00753796.0160_1357005474.67.mpg ! decodebin name=decoder decoder. ! queue ! audioconvert ! alsasink device=surround51 decoder. ! deinterlace ! videoconvert ! xvimagesink",&error);
// 		pipeline = gst_parse_launch("filesrc location=/home/jalips/data/mytv/recordings/EP00753796.0160_1357005474.67.mpg ! decodebin name=decoder decoder. ! queue ! audioconvert ! audioresample ! alsasink decoder. ! deinterlace ! videoconvert ! xvimagesink",&error);
		pipeline = gst_parse_launch("filesrc location=test.mpg ! decodebin name=decoder decoder. ! queue ! audioconvert ! audioresample ! alsasink decoder. ! deinterlace ! videoconvert ! xvimagesink",&error);
// 		pipeline = gst_parse_launch("filesrc location=/home/jalips/data/dwhelper/Blondes.avi ! decodebin name=decoder decoder. ! queue ! audioconvert ! audioresample ! alsasink decoder. ! deinterlace ! videoconvert ! xvimagesink",&error);
// 																 filesrc location=/home/jalips/data/mytv/recordings/EP00753796.0160_1357005474.67.mpg ! decodebin name=decoder decoder. ! queue ! audioconvert ! audioresample ! alsasink decoder. ! deinterlace ! videoconvert ! xvimagesink


// 		/* Create the elements */
// 		pipeline = gst_element_factory_make ("playbin", "pipeline");
// 		
// 		if (!pipeline) {
// 			g_printerr ("Not all elements could be created.\n");
// 			return -1;
// 		}
// 		 
// 		/* Set the URI to play */
// 		g_object_set (pipeline, "uri", "file:/home/jalips/data/mytv/recordings/EP00753796.0160_1357005474.67.mpg", NULL);

		gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline)),(GstBusFunc) bus_call, window);

// 		printf ("Parse error: %s\n", error->message);


//     src = gst_element_factory_make("videotestsrc", NULL);
// 
//     sink = gst_element_factory_make("xvimagesink", "videosink");

//     if (!sink)
//         g_print ("output could not be found - check your install\n");

//     gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
//     g_object_set(G_OBJECT(sink), "force-aspect-ratio", TRUE, NULL);

//     /* link everything together */
//     if (!gst_element_link(src, sink)) {
//         g_print ("Failed to link one or more elements!\n");
//         return -1;
//     }

		// attach key press signal to key press callback
		gtk_widget_set_events(window, GDK_KEY_PRESS_MASK);
		g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(key_press_event_cb), NULL);
		g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy_cb), loop);

		/* run */
		make_window_black(window);
		gtk_widget_show_all(window);

		ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);

		if (ret == GST_STATE_CHANGE_FAILURE) {
				g_print("Failed to start up pipeline!\n");
				return 1;
		}

		g_main_loop_run(loop);

		/* clean up */
		gst_element_set_state(pipeline, GST_STATE_NULL);
		gst_object_unref(pipeline);

		return 0;
}

