/***************************************************************************
 *   Copyright (C) 2004-2005 by Nicolas Boichat                            *
 *   Copyright (C) 2004-2026 by DDCcontrol authors and contributors        *
 *   nicolas@boichat.ch                                                    *
 *                                                                         *
 *   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 2 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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
 ***************************************************************************/

#include "config.h"
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "gui.h"
#include "internal.h"

#include "daemon/dbus_client.h"

GtkWidget* grid;

GtkWidget *combo_box;
GtkWidget* refresh_monitors_button;

GtkWidget *messagebox = NULL;
GtkWidget *messagelabel = NULL;
GtkWidget *messagebutton = NULL;
GtkWidget *statuslabel = NULL;

GtkWidget* close_button = NULL;

GtkWidget* choice_hbox = NULL;
GtkWidget* profile_hbox = NULL;
GtkWidget* bottom_hbox = NULL;

GtkWidget* main_app_window = NULL;

GtkWidget* monitor_manager = NULL;
GtkWidget* profile_manager = NULL;

GtkWidget* profile_manager_button = NULL;
GtkWidget* saveprofile_button = NULL;
GtkWidget* cancelprofile_button = NULL;
GtkWidget* refresh_controls_button = NULL;

struct monitor* mon;

GdkMonitor* current_monitor = NULL; /* current monitor */
int num_monitor; /* total number of monitors */

struct monitorlist* monlist;

gulong combo_box_changed_handler_id = 0;

int mainrow = 0; /* Main center row in the table widget */

/* Indicate what is now displayed at the center of the main window:
 *  0 - Monitor manager
 *  1 - Profile manager
 */
int current_main_component = 0;

/* Current monitor id, and next one. */
int currentid = -1;
int nextid = -1;

static GMutex combo_change_mutex;

DDCControl *ddccontrol_proxy;
int hide_unsupported_monitor_warning = 0;

static int verbosity = 0;

static gboolean parse_verbosity_option(const gchar *option_name, const gchar *value, gpointer data, GError **error)
{
	(void)option_name;
	(void)value;
	(void)data;
	(void)error;

	verbosity++;

	return TRUE;
}

static int can_use_dbus_daemon(void)
{
	const char *disable_envvar = getenv("DDCCONTROL_NO_DAEMON");

	if (disable_envvar != NULL && strlen(disable_envvar) > 0)
		return 0;

	return 1;
}

static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    return FALSE;
}

static void destroy( GtkWidget *widget,
                     gpointer   data )
{
    gtk_main_quit ();
}

static void loadprofile_callback(GtkWidget *widget, gpointer data)
{
	set_current_main_component(1);
}

static void combo_change(GtkWidget *widget, gpointer data)
{
	nextid = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
	if (!g_mutex_trylock(&combo_change_mutex)) {
		if (get_verbosity())
			printf("Tried to change to %d, but mutex locked.\n", gtk_combo_box_get_active(GTK_COMBO_BOX(widget)));
		return;
	}
	
	gtk_widget_set_sensitive(widget, FALSE);
	
	while (currentid != nextid) {
		if (get_verbosity())
			printf("currentid(%d) != nextid(%d), trying...\n", currentid, nextid);
		currentid = nextid;
		int i = 0;
	
		if (monitor_manager != NULL) {
			delete_monitor_manager();
			gtk_widget_destroy(monitor_manager);
			monitor_manager = NULL;
		}
	
		char buffer[256];
		
		struct monitorlist* current;
		
		for (current = monlist;; current = current->next)
		{
			g_assert(current != NULL);
			if (i == currentid)
			{
				snprintf(buffer, 256, "%s: %s", current->filename, current->name);
				create_monitor_manager(current);
				if (monitor_manager) {
					gtk_widget_set_sensitive(refresh_controls_button, TRUE);
				}
				else {
					gtk_widget_set_sensitive(close_button, TRUE);
					gtk_widget_set_sensitive(choice_hbox, TRUE);
				}
				break;
			}
			i++;
		}
		
		if (monitor_manager) {
			gtk_grid_attach(GTK_GRID(grid), monitor_manager, 0, mainrow, 1, 1);
			gtk_widget_set_hexpand(monitor_manager, TRUE);
			gtk_widget_set_vexpand(monitor_manager, TRUE);
			gtk_widget_set_margin_top(monitor_manager, 5);
			gtk_widget_set_margin_bottom(monitor_manager, 5);
			gtk_widget_set_margin_start(monitor_manager, 5);
			gtk_widget_set_margin_end(monitor_manager, 5);
			gtk_grid_attach(GTK_GRID(grid), profile_manager, 0, mainrow, 1, 1);
			gtk_widget_set_hexpand(profile_manager, TRUE);
			gtk_widget_set_vexpand(profile_manager, TRUE);
			gtk_widget_set_margin_top(profile_manager, 5);
			gtk_widget_set_margin_bottom(profile_manager, 5);
			gtk_widget_set_margin_start(profile_manager, 5);
			gtk_widget_set_margin_end(profile_manager, 5);
		}
		
		while (gtk_events_pending ())
			gtk_main_iteration ();
	}
	
	if (get_verbosity())
		printf("currentid == nextid (%d)\n", currentid);
	
	gtk_widget_set_sensitive(widget, TRUE);
	g_mutex_unlock(&combo_change_mutex);
}

static gboolean window_changed(GtkWidget *widget, 
				GdkEventConfigure *event,
				gpointer user_data)
{
	if (num_monitor == 2) { // If there are more than two monitors, we need a configuration menu
		int i;
		struct monitorlist* current;
		
		if (monlist == NULL) {
			if (get_verbosity())
				printf("monlist == NULL\n");
			return FALSE;
		}
		
		i = 0;
		for (current = monlist; current != NULL; current = current->next) i++;
		
		if (i != 2) { // Every monitor does not support DDC/CI, or there are more monitors plugged-in
			//printf("i : %d\n", i);
			return FALSE;
		}
		
		GdkMonitor* monitor = gdk_display_get_monitor_at_window(gdk_display_get_default(), gtk_widget_get_window(main_app_window));

		if (monitor != current_monitor) {
			int k = nextid;
			if (get_verbosity())
				printf(_("Monitor changed (combo index %d).\n"), k);
			k = (k == 0) ? 1 : 0;
			current_monitor = monitor;
			gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), k);
		}
		
		//g_warning(_("Could not find the current monitor in Xinerama monitors list."));
	}
	
	return FALSE;
}

/* Enable or disable widgets (monitor choice, close/refresh button) */
static void widgets_set_sensitive(gboolean sensitive)
{
	gtk_widget_set_sensitive(choice_hbox, sensitive);
	gtk_widget_set_sensitive(refresh_controls_button, sensitive && (current_main_component == 0));
	gtk_widget_set_sensitive(close_button, sensitive);
	gtk_widget_set_sensitive(profile_manager_button, sensitive && (current_main_component == 0));
	gtk_widget_set_sensitive(saveprofile_button, sensitive);
	gtk_widget_set_sensitive(cancelprofile_button, sensitive);
}

void set_current_main_component(int component) {
	g_assert((component == 0) || (component == 1));
	
	current_main_component = component;
	
	if (!monitor_manager)
		return;
	
	if (current_main_component == 0) {
		gtk_widget_show(monitor_manager);
		gtk_widget_hide(profile_manager);
		gtk_widget_set_sensitive(refresh_controls_button, TRUE);
		gtk_widget_set_sensitive(profile_manager_button, TRUE);
	}
	else if (current_main_component == 1) {
		gtk_widget_hide(monitor_manager);
		gtk_widget_show(profile_manager);
		gtk_widget_set_sensitive(refresh_controls_button, FALSE);
		gtk_widget_set_sensitive(profile_manager_button, FALSE);
	}
}

/* Set the status message */
void set_status(char* message) {
	gtk_label_set_text(GTK_LABEL(statuslabel), message);
}

static void messagebutton_callback(GtkButton *button, gpointer user_data)
{
	set_message("");
}

void set_message(char* message) {
	set_message_ok(message, 0);
}

/* Show a message on top of every other controls, with a ok button
 * if the user can hide it himself. */
void set_message_ok(char* message, int with_ok)
{
	gtk_widget_show(messagebutton);
	if (!message[0]) {
		gtk_widget_hide(messagebox);
		if (monitor_manager) {
			set_current_main_component(current_main_component);
		}
		
		widgets_set_sensitive(TRUE);
		
		return;
	}
	
	gtk_label_set_markup(GTK_LABEL(messagelabel), message);
	gtk_label_set_selectable(GTK_LABEL(messagelabel), TRUE);

	widgets_set_sensitive(FALSE);
	
	gtk_widget_show(messagebox);
	if (with_ok) {
		gtk_widget_show(messagebutton);
	}
	else {
		gtk_widget_hide(messagebutton);
	}
	
	if (monitor_manager) {
		gtk_widget_hide(monitor_manager);
		gtk_widget_hide(profile_manager);
	}
	
	while (gtk_events_pending())
		gtk_main_iteration();
}

/* Create a new button with an image and a label packed into it
 * and return the button. */
GtkWidget *button_from_icon_name(const gchar * icon_name, const gchar *label_text, const gchar *tool_tip)
{
	GtkWidget *box;
	GtkWidget *label = NULL;
	GtkWidget *image;
	GtkWidget *button;
	
	button = gtk_button_new();
	
	/* Create box for image and label */
	box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
	gtk_container_set_border_width(GTK_CONTAINER (box), 1);
	
	/* Now on to the image stuff */
	image = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_BUTTON);
	gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 3);
	gtk_widget_show(image);

	if (label_text) {
		/* Create a label for the button */
		label = gtk_label_new_with_mnemonic(label_text);
		
		/* Pack the image and label into the box */
		gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 3);
		
		gtk_widget_show(label);
	}
	
	gtk_widget_show(box);
	
	gtk_container_add (GTK_CONTAINER(button), box);
	
	g_object_set_data(G_OBJECT(button), "button_label", label);
	
	if (tool_tip) {
		gtk_widget_set_tooltip_text(GTK_WIDGET(button), tool_tip);
	}
	
	return button;
}

static void probe_monitors(GtkWidget *widget, gpointer data) {
	if (combo_box_changed_handler_id)
		g_signal_handler_disconnect(G_OBJECT(combo_box), combo_box_changed_handler_id);
	
	gtk_list_store_clear(GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box))));
	
	set_message(_("Probing for available monitors..."));
	// TODO: rescan on button, initial get only
	ddcci_free_list(monlist);
	monlist = NULL;

	if (can_use_dbus_daemon())
		monlist = ddcci_dbus_rescan_monitors(ddccontrol_proxy);
	else
		monlist = ddcci_probe();

	const struct monitorlist* current;
	
	char buffer[256];
	
	for (current = monlist; current != NULL; current = current->next)
	{
		snprintf(buffer, 256, "%s: %s",
			current->filename, current->name);
		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), buffer);
	}
	
	combo_box_changed_handler_id = g_signal_connect(G_OBJECT(combo_box), "changed", G_CALLBACK(combo_change), NULL);
	
	currentid = -1;
	nextid = -1;
	
	if (monlist) {
		widgets_set_sensitive(TRUE);
		gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), 0);
	}
	else {
		widgets_set_sensitive(FALSE);
		gtk_widget_set_sensitive(close_button, TRUE);
		gtk_widget_set_sensitive(refresh_controls_button, TRUE);
		set_message(_(
			"No monitor supporting DDC/CI available.\n\n"
			"If your graphics card need it, please check all the required kernel modules are loaded (i2c-dev, and your framebuffer driver).\n\n"
			"On many laptops, the internal eDP/LVDS panel does not expose DDC/CI, so only external monitors may work.\n\n"
			"For support, include output from:\n"
			"LANG=C LC_ALL=C ddccontrol -p -c -d"
			   ));
	}
}

int main( int argc, char *argv[] )
{
	GError *option_error = NULL;
	GOptionContext *option_context = NULL;
	const GOptionEntry option_entries[] = {
		{ "hide-unsupported-warning", 0, 0, G_OPTION_ARG_NONE, &hide_unsupported_monitor_warning,
		  N_("Hide unsupported monitor warning when using fallback profiles"), NULL },
		{ "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, parse_verbosity_option,
		  N_("Increase verbosity (use multiple times for more output)"), NULL },
		{ NULL }
	};
	
	mon = NULL;
	monitor_manager = NULL;
	
#ifdef HAVE_GETTEXT
	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	bindtextdomain("ddccontrol-db", LOCALEDIR);
	bind_textdomain_codeset(PACKAGE, "UTF-8");
	bind_textdomain_codeset("ddccontrol-db", "UTF-8");
	textdomain(PACKAGE);
#endif

	option_context = g_option_context_new(NULL);
	g_option_context_add_main_entries(option_context, option_entries, PACKAGE);
	g_option_context_add_group(option_context, gtk_get_option_group(FALSE));

	if (!g_option_context_parse(option_context, &argc, &argv, &option_error)) {
		fprintf(stderr, "%s\n", option_error->message);
		g_error_free(option_error);
		g_option_context_free(option_context);
		return 1;
	}

	g_option_context_free(option_context);

	gtk_init(&argc, &argv);

	ddcci_verbosity(verbosity);

	if (can_use_dbus_daemon()) {
		ddccontrol_proxy = ddcci_dbus_open_proxy();
		if(ddccontrol_proxy == NULL) {
			printf(_("Failed to open D-Bus proxy, try with DDCCONTROL_NO_DAEMON=1.\n"));
			return 1;
		}
	} else {
		ddccontrol_proxy = NULL;
	}

	g_mutex_init(&combo_change_mutex);
	
	/* Full screen patterns test */
	/*create_fullscreen_patterns_window();
	show_pattern();
	gtk_main();*/
	
	if (!ddcci_init(NULL)) {
		printf(_("Unable to initialize ddcci library.\n"));
		GtkWidget* dialog = gtk_message_dialog_new(
				GTK_WINDOW(main_app_window),
				GTK_DIALOG_DESTROY_WITH_PARENT,
				GTK_MESSAGE_ERROR,
				GTK_BUTTONS_CLOSE,
				_("Unable to initialize ddcci library, see console for more details.\n"));
		gtk_dialog_run (GTK_DIALOG (dialog));
		gtk_widget_destroy (dialog);
		return 1;
	}
	
	gtk_window_set_default_icon_name ("gddccontrol");

	main_app_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	
	gtk_window_set_title(GTK_WINDOW(main_app_window),_("Monitor settings"));
	
	gtk_window_set_default_size(GTK_WINDOW(main_app_window), 500, 500);

	gtk_window_set_position (GTK_WINDOW (main_app_window), GTK_WIN_POS_CENTER);
	
	g_signal_connect (G_OBJECT (main_app_window), "delete_event",
				G_CALLBACK (delete_event), NULL);
	
	g_signal_connect (G_OBJECT (main_app_window), "destroy",
				G_CALLBACK (destroy), NULL);

	g_signal_connect (G_OBJECT (main_app_window), "configure-event",
				G_CALLBACK (window_changed), NULL);
	
	gtk_container_set_border_width (GTK_CONTAINER (main_app_window), 4);

	GtkAccelGroup *accel_group = gtk_accel_group_new();
	gtk_window_add_accel_group(GTK_WINDOW(main_app_window), accel_group);

	grid = gtk_grid_new();
	gtk_widget_show (grid);
	int crow = 0; /* Current row */
	
	/* Monitor choice combo box */
	choice_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
	
	GtkWidget* label = gtk_label_new(_("Current monitor: "));
	gtk_widget_show(label);
	gtk_box_pack_start(GTK_BOX(choice_hbox),label, 0, 0, 0);
	
	combo_box = gtk_combo_box_text_new();
	
	gtk_widget_show(combo_box);

	gtk_box_pack_start(GTK_BOX(choice_hbox),combo_box, 1, 1, 0);

	refresh_monitors_button = button_from_icon_name("view-refresh", NULL, _("Refresh monitor list"));
	g_signal_connect(G_OBJECT(refresh_monitors_button), "clicked", G_CALLBACK(probe_monitors), NULL);
	gtk_widget_add_accelerator(refresh_monitors_button, "clicked", accel_group, GDK_KEY_F5, 0, GTK_ACCEL_VISIBLE);
	g_object_unref(accel_group);
	gtk_widget_show(refresh_monitors_button);
	gtk_box_pack_start(GTK_BOX(choice_hbox),refresh_monitors_button, 0, 0, 0);
	
	gtk_grid_attach(GTK_GRID(grid), choice_hbox, 0, crow, 1, 1);
	gtk_widget_set_hexpand(choice_hbox, TRUE);
	gtk_widget_set_margin_top(choice_hbox, 5);
	gtk_widget_set_margin_bottom(choice_hbox, 5);
	gtk_widget_set_margin_start(choice_hbox, 5);
	gtk_widget_set_margin_end(choice_hbox, 5);
	crow++;
	gtk_widget_show(choice_hbox);
	
	GtkWidget* hsep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
	gtk_widget_show (hsep);
	gtk_grid_attach(GTK_GRID(grid), hsep, 0, crow, 1, 1);
	gtk_widget_set_hexpand(hsep, TRUE);
	crow++;
	
	/* Toolbar (profile...) */
	profile_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
	
	profile_manager_button = button_from_icon_name("folder-symbolic", _("Profile manager"), NULL);
	g_signal_connect(G_OBJECT(profile_manager_button), "clicked", G_CALLBACK(loadprofile_callback), NULL);

	gtk_box_pack_start(GTK_BOX(profile_hbox), profile_manager_button, 0, 0, 0);
	gtk_widget_show (profile_manager_button);
	gtk_widget_set_sensitive(profile_manager_button, FALSE);
	
	saveprofile_button = button_from_icon_name("document-save", _("Save profile"), NULL);
	g_signal_connect(G_OBJECT(saveprofile_button), "clicked", G_CALLBACK(saveprofile_callback), NULL);

	gtk_box_pack_start(GTK_BOX(profile_hbox), saveprofile_button, 0, 0, 0);
	gtk_widget_set_sensitive(saveprofile_button, FALSE);
	
	cancelprofile_button = button_from_icon_name("edit-clear-all", _("Cancel profile creation"), NULL);
	g_signal_connect(G_OBJECT(cancelprofile_button), "clicked", G_CALLBACK(cancelprofile_callback), NULL);

	gtk_box_pack_start(GTK_BOX(profile_hbox), cancelprofile_button, 0, 0, 0);
	gtk_widget_set_sensitive(cancelprofile_button, FALSE);
	
	gtk_widget_show (profile_hbox);
	gtk_grid_attach(GTK_GRID(grid), profile_hbox, 0, crow, 1, 1);
	gtk_widget_set_hexpand(profile_hbox, TRUE);
	gtk_widget_set_margin_top(profile_hbox, 8);
	gtk_widget_set_margin_bottom(profile_hbox, 8);
	gtk_widget_set_margin_start(profile_hbox, 8);
	gtk_widget_set_margin_end(profile_hbox, 8);
	crow++;
	
	hsep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
	gtk_widget_show (hsep);
	gtk_grid_attach(GTK_GRID(grid), hsep, 0, crow, 1, 1);
	gtk_widget_set_hexpand(hsep, TRUE);
	crow++;
	
	/* Status message label (used when loading or refreshing, or when displaying some kind of warnings) */
	messagebox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
	
	messagelabel = gtk_label_new ("");
	gtk_label_set_line_wrap(GTK_LABEL(messagelabel), TRUE);
	gtk_box_pack_start(GTK_BOX(messagebox), messagelabel, 1, 1, 0);
	gtk_widget_show(messagelabel);
	
	messagebutton = gtk_button_new_with_mnemonic(_("OK"));
	g_signal_connect(G_OBJECT(messagebutton), "clicked", G_CALLBACK(messagebutton_callback), NULL);
	gtk_widget_set_halign(messagebutton, GTK_ALIGN_CENTER);
	gtk_widget_set_valign(messagebutton, GTK_ALIGN_CENTER);
	gtk_widget_show(messagebutton);
	
	gtk_box_pack_start(GTK_BOX(messagebox), messagebutton, 0, 0, 10);
	
	gtk_grid_attach(GTK_GRID(grid), messagebox, 0, crow, 1, 1);
	gtk_widget_set_hexpand(messagebox, TRUE);
	gtk_widget_set_vexpand(messagebox, TRUE);
	gtk_widget_set_margin_top(messagebox, 5);
	gtk_widget_set_margin_bottom(messagebox, 5);
	gtk_widget_set_margin_start(messagebox, 5);
	gtk_widget_set_margin_end(messagebox, 5);
	mainrow = crow;
	crow++;
	
	hsep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
	gtk_widget_show (hsep);
	gtk_grid_attach(GTK_GRID(grid), hsep, 0, crow, 1, 1);
	gtk_widget_set_hexpand(hsep, TRUE);
	crow++;
	
	/* Refresh and close buttons */
	bottom_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
	
	statuslabel = gtk_label_new("");
	gtk_label_set_line_wrap(GTK_LABEL(statuslabel), TRUE);
	gtk_box_pack_start(GTK_BOX(bottom_hbox),statuslabel, TRUE, TRUE, 0);
	gtk_widget_show(statuslabel);
	
	GtkWidget* br_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 30);
	gtk_widget_set_halign(br_hbox, GTK_ALIGN_END);
	gtk_widget_set_valign(br_hbox, GTK_ALIGN_CENTER);
	
	refresh_controls_button = button_from_icon_name("view-refresh", _("Refresh"), _("Refresh all controls"));
	g_signal_connect(G_OBJECT(refresh_controls_button),"clicked",G_CALLBACK (refresh_all_controls), NULL);

	gtk_box_pack_start(GTK_BOX(br_hbox),refresh_controls_button,0,0,0);
	gtk_widget_show (refresh_controls_button);
	gtk_widget_set_sensitive(refresh_controls_button, FALSE);
	
	close_button = button_from_icon_name("window-close", _("Close"), NULL);
	g_signal_connect(G_OBJECT(close_button),"clicked",G_CALLBACK (destroy), NULL);

	gtk_box_pack_start(GTK_BOX(br_hbox),close_button,0,0,0);
	gtk_widget_show (close_button);
	
	gtk_widget_show (br_hbox);
	
	gtk_box_pack_start(GTK_BOX(bottom_hbox),br_hbox, TRUE, TRUE,0);
	gtk_widget_show (bottom_hbox);
	gtk_grid_attach(GTK_GRID(grid), bottom_hbox, 0, crow, 1, 1);
	gtk_widget_set_hexpand(bottom_hbox, TRUE);
	gtk_widget_set_margin_top(bottom_hbox, 8);
	gtk_widget_set_margin_bottom(bottom_hbox, 8);
	gtk_widget_set_margin_start(bottom_hbox, 8);
	gtk_widget_set_margin_end(bottom_hbox, 8);
	crow++;
	
	gtk_container_add (GTK_CONTAINER(main_app_window), grid);
	
	gtk_widget_show(main_app_window);
	
	GdkDisplay* display = gdk_display_get_default();

	num_monitor = gdk_display_get_n_monitors(display);

	/*for (i = 0; i < num_monitor; i++) {
		GdkRectangle dest;
		GdkMonitor* m = gdk_display_get_monitor(display, i);
		gdk_monitor_get_geometry(m, &dest);
		printf("%d: %d, %d %dx%d\n", i, dest.x, dest.y, dest.width, dest.height);
	}*/

	current_monitor = gdk_display_get_monitor_at_window(display, gtk_widget_get_window(main_app_window));
	
	probe_monitors(NULL, NULL);
	
/*	moninfo = gtk_label_new ();
	gtk_misc_set_alignment(GTK_MISC(moninfo), 0, 0);
	
	gtk_table_attach(GTK_TABLE(table), moninfo, 0, 1, 1, 2, GTK_FILL_EXPAND, 0, 5, 5);*/
	
	gchar* tmp = g_strdup_printf(_("Welcome to gddccontrol %s."), VERSION);
	set_status(tmp);
	g_free(tmp);
	
	gtk_main();
	
	delete_monitor_manager();
	
	ddcci_free_list(monlist);
	
	ddcci_release();
	
	return 0;
}
