/*
 * Remmina - The GTK+ Remote Desktop Client
 * Copyright (C) 2009-2011 Vic Lee
 * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
 * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo
 *
 * 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.
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of portions of this program with the
 *  OpenSSL library under certain conditions as described in each
 *  individual source file, and distribute linked combinations
 *  including the two.
 *  You must obey the GNU General Public License in all respects
 *  for all of the code used other than OpenSSL. *  If you modify
 *  file(s) with this exception, you may extend this exception to your
 *  version of the file(s), but you are not obligated to do so. *  If you
 *  do not wish to do so, delete this exception statement from your
 *  version. *  If you delete this exception statement from all source
 *  files in the program, then also delete it here.
 *
 */

#include <glib/gi18n.h>
#include "config.h"
#include "remmina_public.h"
#include "remmina_widget_pool.h"
#include "remmina_main.h"
#include "remmina_message_panel.h"
#include "remmina_masterthread_exec.h"
#include "remmina/remmina_trace_calls.h"


typedef struct
{

	RemminaMessagePanelCallback response_callback;
	void *response_callback_data;
	GtkWidget *w[REMMINA_MESSAGE_PANEL_MAXWIDGETID];

} RemminaMessagePanelPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (RemminaMessagePanel, remmina_message_panel, GTK_TYPE_BOX)


enum {
  RESPONSE,
  LAST_SIGNAL
};

static guint messagepanel_signals[LAST_SIGNAL];

static const gchar btn_response_key[] = "btn_response";

static void remmina_message_panel_init (RemminaMessagePanel *mp)
{
	TRACE_CALL(__func__);
}

static void remmina_message_panel_class_init(RemminaMessagePanelClass *class)
{
	TRACE_CALL(__func__);

	messagepanel_signals[RESPONSE] =
		g_signal_new ("response",
			G_OBJECT_CLASS_TYPE (class),
			G_SIGNAL_RUN_LAST,
			G_STRUCT_OFFSET (RemminaMessagePanelClass, response),
			NULL, NULL,
			NULL,
			G_TYPE_NONE, 1,
			G_TYPE_INT);
}

RemminaMessagePanel *remmina_message_panel_new()
{
	TRACE_CALL(__func__);
	RemminaMessagePanelPrivate *priv;
	RemminaMessagePanel* mp;
	mp = (RemminaMessagePanel*)g_object_new(REMMINA_TYPE_MESSAGE_PANEL,
		"orientation", GTK_ORIENTATION_VERTICAL,
		"spacing", 0,
		NULL);

	priv = remmina_message_panel_get_instance_private(mp);

	priv->response_callback = NULL;
	priv->response_callback_data = NULL;

	/* Set widget class, for CSS styling */
	gtk_style_context_add_class(gtk_widget_get_style_context(GTK_WIDGET(mp)), "message_panel");
	gtk_style_context_add_class(gtk_widget_get_style_context(GTK_WIDGET(mp)), "background");

	return mp;
}

static void remmina_message_panel_button_clicked_callback(
	GtkButton *button, gpointer user_data)
{
	TRACE_CALL(__func__);
	RemminaMessagePanel *mp = (RemminaMessagePanel*)user_data;
	RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);

	gint btn_data;

	btn_data = (gint)((gint64)g_object_get_data(G_OBJECT(button), btn_response_key));

	/* Calls the callback, if defined */
	if (priv->response_callback != NULL)
		(*priv->response_callback)(priv->response_callback_data, btn_data);

}

void remmina_message_panel_setup_progress(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
{
	/*
	 * Setup a message panel to show a spinner, a message like "Connecting…",
	 * and a button to cancel the action in progress
	 *
	 */

	TRACE_CALL(__func__);
	GtkBox *hbox;
	GtkWidget *w;
	RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);

	if ( !remmina_masterthread_exec_is_main_thread() ) {
		printf("WARNING: %s called in a subthread. This should not happen.\n", __func__);
		raise(SIGINT);
	}

	hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));

	/* A spinner */
	w = gtk_spinner_new();
	gtk_box_pack_start(hbox, w, FALSE, FALSE, 0);
	gtk_spinner_start(GTK_SPINNER(w));

	/* A message */
	w = gtk_label_new(message);
	gtk_box_pack_start(hbox, w, TRUE, TRUE, 0);

	priv->response_callback = response_callback;
	priv->response_callback_data = response_callback_data;

	/* A button to cancel the action. The cancel button is available
	 * only when a response_callback function is defined. */
	if (response_callback) {
		w = gtk_button_new_with_label(_("Cancel"));
		gtk_box_pack_end(hbox, w, FALSE, FALSE, 0);
		g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_CANCEL);
		g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
	}

	gtk_box_pack_start(GTK_BOX(mp), GTK_WIDGET(hbox), TRUE, TRUE, 0);

	gtk_widget_show_all(GTK_WIDGET(mp));

}

void remmina_message_panel_setup_message(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
{
	/*
	 * Setup a message panel to a message to read like "Cannot connect…",
	 * and a button to close the panel
	 *
	 */

	TRACE_CALL(__func__);
	GtkBox *hbox;
	GtkWidget *w;
	RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);

	if ( !remmina_masterthread_exec_is_main_thread() ) {
		printf("WARNING: %s called in a subthread. This should not happen.\n", __func__);
	}

	hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));

	/* A message */
	w = gtk_label_new(message);
	gtk_box_pack_start(hbox, w, TRUE, TRUE, 0);

	/* A button to confirm reading */
	w = gtk_button_new_with_label(_("Close"));
	gtk_box_pack_end(hbox, w, FALSE, FALSE, 0);

	priv->response_callback = response_callback;
	priv->response_callback_data = response_callback_data;

	g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_OK);
	g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);

	gtk_box_pack_start(GTK_BOX(mp), GTK_WIDGET(hbox), TRUE, TRUE, 0);

	gtk_widget_show_all(GTK_WIDGET(mp));

}

void remmina_message_panel_setup_question(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data, gboolean accept)
{
	/*
	 * Setup a message panel to a message to read like "Do you accept ?",
	 * and a pair of button for Yes and No
	 * message is an HTML string
	 * Callback will receive GTK_RESPONSE_NO for No, GTK_RESPONSE_YES for Yes
	 *
	 */

	TRACE_CALL(__func__);
	GtkWidget *grid;
	GtkWidget *bbox;
	GtkWidget *w;
	RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);

	if ( !remmina_masterthread_exec_is_main_thread() ) {
		printf("WARNING: %s called in a subthread. This should not happen. Raising SIGINT for debugging.\n", __func__);
		raise(SIGINT);
	}

	/* Create grid */
	grid = gtk_grid_new();
	gtk_widget_set_halign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
	gtk_widget_set_valign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
	gtk_widget_show(grid);
	gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
	gtk_grid_set_column_spacing(GTK_GRID(grid), 6);

	/* A message, in HTML format */
	w = gtk_label_new(NULL);
	gtk_label_set_markup(GTK_LABEL(w), message);

	gtk_widget_set_halign(GTK_WIDGET(w), GTK_ALIGN_START);
	gtk_widget_set_valign(GTK_WIDGET(w), GTK_ALIGN_FILL);
	gtk_widget_set_margin_top (GTK_WIDGET(w), 18);
	gtk_widget_set_margin_bottom (GTK_WIDGET(w), 9);
	gtk_widget_set_margin_start (GTK_WIDGET(w), 18);
	gtk_widget_set_margin_end (GTK_WIDGET(w), 18);
	gtk_widget_show(w);
	gtk_grid_attach(GTK_GRID(grid), w, 0, 0, 2, 1);

	if (accept){
		w = gtk_label_new(_("Do you accept?"));
		gtk_grid_attach(GTK_GRID(grid), w, 0, 1, 1, 1);
		/* A button for yes and one for no */
		bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
		gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_START);
		gtk_grid_attach(GTK_GRID(grid), bbox, 0, 2, 1, 1);
		w = gtk_button_new_with_label(_("Yes"));
		gtk_widget_set_valign(GTK_WIDGET(w), GTK_ALIGN_CENTER);
		g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_YES);
	}
	else {
		/* A button for yes and one for no */
		bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
		gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_START);
		gtk_grid_attach(GTK_GRID(grid), bbox, 0, 1, 1, 1);
		w = gtk_button_new_with_label(_("Yes"));
		gtk_widget_set_valign(GTK_WIDGET(w), GTK_ALIGN_CENTER);
		g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_YES);
	}
	
	g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
	gtk_container_add(GTK_CONTAINER(bbox), w);

	w = gtk_button_new_with_label(_("No"));
	gtk_widget_set_valign(GTK_WIDGET(w), GTK_ALIGN_CENTER);
	g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_NO);

	priv->response_callback = response_callback;
	priv->response_callback_data = response_callback_data;

	g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
	gtk_container_add(GTK_CONTAINER(bbox), w);

	gtk_box_pack_start(GTK_BOX(mp), GTK_WIDGET(grid), TRUE, TRUE, 0);

	gtk_widget_show_all(GTK_WIDGET(mp));

}

void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data, const gchar *title, const gchar *password_prompt, unsigned flags)
{
	TRACE_CALL(__func__);
	GtkWidget *grid;
	GtkWidget *password_entry;
	GtkWidget *username_entry;
	GtkWidget *domain_entry;
	GtkWidget *save_password_switch;
	GtkWidget *widget;
	GtkWidget *bbox;
	GtkWidget *button_ok;
	GtkWidget *button_cancel;
	int grid_row;

	RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);

	if ( !remmina_masterthread_exec_is_main_thread() ) {
		printf("WARNING: %s called in a subthread. This should not happen. Raising SIGINT to debug.\n", __func__);
		raise(SIGINT);
	}

	/* Create grid */
	grid = gtk_grid_new();
	gtk_widget_set_halign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
	gtk_widget_set_valign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
	gtk_widget_show(grid);
	gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
	gtk_grid_set_column_spacing(GTK_GRID(grid), 6);

	/* Entries */

	grid_row = 0;
	widget = gtk_label_new(title);
	gtk_style_context_add_class(gtk_widget_get_style_context(widget), "title_label");
	gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
	gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_FILL);
	gtk_widget_set_margin_top (GTK_WIDGET(widget), 18);
	gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 9);
	gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
	gtk_widget_set_margin_end (GTK_WIDGET(widget), 18);
	gtk_widget_show(widget);
	gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 3, 1);
	grid_row++;


	if (flags & REMMINA_MESSAGE_PANEL_FLAG_USERNAME) {
		widget = gtk_label_new(_("Username"));
		gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
		gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
		gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
		gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
		gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
		gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
		gtk_widget_show(widget);
		gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);

		username_entry = gtk_entry_new();
		gtk_widget_set_halign(GTK_WIDGET(username_entry), GTK_ALIGN_FILL);
		gtk_widget_set_valign(GTK_WIDGET(username_entry), GTK_ALIGN_FILL);
		gtk_widget_set_margin_top (GTK_WIDGET(username_entry), 9);
		gtk_widget_set_margin_bottom (GTK_WIDGET(username_entry), 3);
		gtk_widget_set_margin_start (GTK_WIDGET(username_entry), 6);
		gtk_widget_set_margin_end (GTK_WIDGET(username_entry), 18);
		gtk_grid_attach(GTK_GRID(grid), username_entry, 1, grid_row, 2, 1);
		gtk_entry_set_max_length(GTK_ENTRY(username_entry), 100);

		if (flags & REMMINA_MESSAGE_PANEL_FLAG_USERNAME_READONLY) {
			g_object_set(username_entry, "editable", FALSE, NULL);
		}

		grid_row++;
	} else {
		username_entry = NULL;
	}

	/* The password/key field */
	widget = gtk_label_new(password_prompt);
	gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
	gtk_widget_set_margin_top (GTK_WIDGET(widget), 3);
	gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
	gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
	gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
	gtk_widget_show(widget);
	gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);

	password_entry = gtk_entry_new();
	gtk_widget_set_halign(GTK_WIDGET(password_entry), GTK_ALIGN_FILL);
	gtk_widget_set_valign(GTK_WIDGET(password_entry), GTK_ALIGN_FILL);
	gtk_widget_set_margin_top (GTK_WIDGET(password_entry), 3);
	gtk_widget_set_margin_bottom (GTK_WIDGET(password_entry), 3);
	gtk_widget_set_margin_start (GTK_WIDGET(password_entry), 6);
	gtk_widget_set_margin_end (GTK_WIDGET(password_entry), 18);
	gtk_entry_set_activates_default (GTK_ENTRY(password_entry), TRUE);
	gtk_grid_attach(GTK_GRID(grid), password_entry, 1, grid_row, 2, 1);
	gtk_entry_set_max_length(GTK_ENTRY(password_entry), 0);
	gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE);
	gtk_entry_set_icon_from_icon_name(GTK_ENTRY(password_entry), GTK_ENTRY_ICON_SECONDARY, "org.remmina.Remmina-password-reveal-symbolic");
	gtk_entry_set_icon_activatable(GTK_ENTRY(password_entry), GTK_ENTRY_ICON_SECONDARY, TRUE);
	g_signal_connect(password_entry, "icon-press", G_CALLBACK(remmina_main_toggle_password_view), NULL);

	grid_row++;

	if (flags & REMMINA_MESSAGE_PANEL_FLAG_DOMAIN) {
		widget = gtk_label_new(_("Domain"));
		gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
		gtk_widget_set_margin_top (GTK_WIDGET(widget), 3);
		gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
		gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
		gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
		gtk_widget_show(widget);
		gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);

		domain_entry = gtk_entry_new();
		gtk_widget_set_halign(GTK_WIDGET(domain_entry), GTK_ALIGN_FILL);
		gtk_widget_set_valign(GTK_WIDGET(domain_entry), GTK_ALIGN_FILL);
		gtk_widget_set_margin_top (GTK_WIDGET(domain_entry), 3);
		gtk_widget_set_margin_bottom (GTK_WIDGET(domain_entry), 3);
		gtk_widget_set_margin_start (GTK_WIDGET(domain_entry), 6);
		gtk_widget_set_margin_end (GTK_WIDGET(domain_entry), 18);
                gtk_entry_set_activates_default (GTK_ENTRY(domain_entry), TRUE);
		gtk_widget_show(domain_entry);
		gtk_grid_attach(GTK_GRID(grid), domain_entry, 1, grid_row, 2, 1);
		gtk_entry_set_max_length(GTK_ENTRY(domain_entry), 100);
		/* if (default_domain && default_domain[0] != '\0') {
			gtk_entry_set_text(GTK_ENTRY(domain_entry), default_domain);
		} */
		grid_row ++;
	} else {
		domain_entry = NULL;
	}


	widget = gtk_label_new(_("Save password"));
	gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
	gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 9);
	gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
	gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
	gtk_widget_show(widget);
	gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
	save_password_switch = gtk_switch_new();
	gtk_widget_set_halign(GTK_WIDGET(save_password_switch), GTK_ALIGN_START);
	gtk_widget_set_valign(GTK_WIDGET(save_password_switch), GTK_ALIGN_FILL);
	gtk_widget_set_margin_top (GTK_WIDGET(save_password_switch), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(save_password_switch), 9);
	gtk_widget_set_margin_start (GTK_WIDGET(save_password_switch), 6);
	gtk_widget_set_margin_end (GTK_WIDGET(save_password_switch), 18);
	gtk_grid_attach(GTK_GRID(grid), save_password_switch, 1, grid_row, 2, 1);
	if (flags & REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSWORD) {
		gtk_switch_set_active(GTK_SWITCH(save_password_switch), TRUE);
	}else  {
		gtk_switch_set_active(GTK_SWITCH(save_password_switch), FALSE);
		gtk_widget_set_sensitive(GTK_WIDGET(save_password_switch), FALSE);
	}
	grid_row ++;

	/* Buttons, ok and cancel */
	bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
	gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_EDGE);
	gtk_box_set_spacing (GTK_BOX (bbox), 40);
	gtk_widget_set_margin_top (GTK_WIDGET(bbox), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(bbox), 18);
	gtk_widget_set_margin_start (GTK_WIDGET(bbox), 18);
	gtk_widget_set_margin_end (GTK_WIDGET(bbox), 18);
	button_ok = gtk_button_new_with_label(_("_OK"));
	gtk_button_set_use_underline(GTK_BUTTON(button_ok), TRUE);
	gtk_widget_set_can_default(button_ok, TRUE);
	gtk_container_add (GTK_CONTAINER (bbox), button_ok);
	/* Buttons, ok and cancel */
	button_cancel = gtk_button_new_with_label(_("_Cancel"));
	gtk_button_set_use_underline(GTK_BUTTON(button_cancel), TRUE);
	gtk_container_add (GTK_CONTAINER (bbox), button_cancel);
	gtk_grid_attach(GTK_GRID(grid), bbox, 0, grid_row, 3, 1);
	/* Pack it into the panel */
	gtk_box_pack_start(GTK_BOX(mp), grid, TRUE, TRUE, 4);

	priv->w[REMMINA_MESSAGE_PANEL_USERNAME] = username_entry;
	priv->w[REMMINA_MESSAGE_PANEL_PASSWORD] = password_entry;
	priv->w[REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSWORD] = save_password_switch;
	priv->w[REMMINA_MESSAGE_PANEL_DOMAIN] = domain_entry;
	priv->w[REMMINA_MESSAGE_PANEL_BUTTONTOFOCUS] = button_ok;

	priv->response_callback = response_callback;
	priv->response_callback_data = response_callback_data;

	if (username_entry) g_signal_connect_swapped (username_entry, "activate", (GCallback)gtk_widget_grab_focus, password_entry);
	g_signal_connect_swapped (password_entry, "activate", (GCallback)gtk_widget_grab_focus, button_ok);
	g_object_set_data(G_OBJECT(button_cancel), btn_response_key, (void *)GTK_RESPONSE_CANCEL);
	g_signal_connect(G_OBJECT(button_cancel), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
	g_object_set_data(G_OBJECT(button_ok), btn_response_key, (void *)GTK_RESPONSE_OK);
	g_signal_connect(G_OBJECT(button_ok), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
}

void remmina_message_panel_setup_auth_x509(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
{
	TRACE_CALL(__func__);

	GtkWidget *grid;
	GtkWidget *widget;
	GtkWidget *bbox;
	GtkWidget *button_ok;
	GtkWidget *button_cancel;
	GtkWidget *cacert_file;
	GtkWidget *cacrl_file;
	GtkWidget *clientcert_file;
	GtkWidget *clientkey_file;
	int grid_row;

	RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);

	if ( !remmina_masterthread_exec_is_main_thread() ) {
		printf("WARNING: %s called in a subthread. This should not happen. Raising SIGINT to debug.\n", __func__);
		raise(SIGINT);
	}

	/* Create grid */
	grid = gtk_grid_new();
	gtk_widget_set_halign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
	gtk_widget_set_valign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
	gtk_widget_show(grid);
	gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
	gtk_grid_set_column_spacing(GTK_GRID(grid), 6);

	/* Entries */
	grid_row = 0;
	widget = gtk_label_new(_("Enter certificate authentication files"));
	gtk_style_context_add_class(gtk_widget_get_style_context(widget), "title_label");
	gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
	gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_FILL);
	gtk_widget_set_margin_top (GTK_WIDGET(widget), 18);
	gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 9);
	gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
	gtk_widget_set_margin_end (GTK_WIDGET(widget), 18);
	gtk_widget_show(widget);
	gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 3, 1);
	grid_row++;

	const gchar *lbl_cacert = _("CA Certificate File");
	widget = gtk_label_new(lbl_cacert);
	gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
	gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
	gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
	gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
	gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
	gtk_widget_show(widget);
	gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
	cacert_file = gtk_file_chooser_button_new(lbl_cacert, GTK_FILE_CHOOSER_ACTION_OPEN);
	gtk_widget_show(cacert_file);
	gtk_widget_set_halign(GTK_WIDGET(cacert_file), GTK_ALIGN_FILL);
	gtk_widget_set_valign(GTK_WIDGET(cacert_file), GTK_ALIGN_FILL);
	gtk_widget_set_margin_top (GTK_WIDGET(cacert_file), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(cacert_file), 3);
	gtk_widget_set_margin_start (GTK_WIDGET(cacert_file), 6);
	gtk_widget_set_margin_end (GTK_WIDGET(cacert_file), 18);
	gtk_grid_attach(GTK_GRID(grid), cacert_file, 1, grid_row, 2, 1);
	grid_row++;

	const gchar *lbl_cacrl = _("CA CRL File");
	widget = gtk_label_new(lbl_cacrl);
	gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
	gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
	gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
	gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
	gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
	gtk_widget_show(widget);
	gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
	cacrl_file = gtk_file_chooser_button_new(lbl_cacrl, GTK_FILE_CHOOSER_ACTION_OPEN);
	gtk_widget_show(cacrl_file);
	gtk_widget_set_halign(GTK_WIDGET(cacrl_file), GTK_ALIGN_FILL);
	gtk_widget_set_valign(GTK_WIDGET(cacrl_file), GTK_ALIGN_FILL);
	gtk_widget_set_margin_top (GTK_WIDGET(cacrl_file), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(cacrl_file), 3);
	gtk_widget_set_margin_start (GTK_WIDGET(cacrl_file), 6);
	gtk_widget_set_margin_end (GTK_WIDGET(cacrl_file), 18);
	gtk_grid_attach(GTK_GRID(grid), cacrl_file, 1, grid_row, 2, 1);
	grid_row++;

	const gchar *lbl_clicert = _("Client Certificate File");
	widget = gtk_label_new(lbl_clicert);
	gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
	gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
	gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
	gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
	gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
	gtk_widget_show(widget);
	gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
	clientcert_file = gtk_file_chooser_button_new(lbl_clicert, GTK_FILE_CHOOSER_ACTION_OPEN);
	gtk_widget_show(clientcert_file);
	gtk_widget_set_halign(GTK_WIDGET(clientcert_file), GTK_ALIGN_FILL);
	gtk_widget_set_valign(GTK_WIDGET(clientcert_file), GTK_ALIGN_FILL);
	gtk_widget_set_margin_top (GTK_WIDGET(clientcert_file), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(clientcert_file), 3);
	gtk_widget_set_margin_start (GTK_WIDGET(clientcert_file), 6);
	gtk_widget_set_margin_end (GTK_WIDGET(clientcert_file), 18);
	gtk_grid_attach(GTK_GRID(grid), clientcert_file, 1, grid_row, 2, 1);
	grid_row++;

	const gchar *lbl_clikey = _("Client Certificate Key");
	widget = gtk_label_new(lbl_clikey);
	gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
	gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
	gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
	gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
	gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
	gtk_widget_show(widget);
	gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
	clientkey_file = gtk_file_chooser_button_new(lbl_clikey, GTK_FILE_CHOOSER_ACTION_OPEN);
	gtk_widget_show(clientkey_file);
	gtk_widget_set_halign(GTK_WIDGET(clientkey_file), GTK_ALIGN_FILL);
	gtk_widget_set_valign(GTK_WIDGET(clientkey_file), GTK_ALIGN_FILL);
	gtk_widget_set_margin_top (GTK_WIDGET(clientkey_file), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(clientkey_file), 3);
	gtk_widget_set_margin_start (GTK_WIDGET(clientkey_file), 6);
	gtk_widget_set_margin_end (GTK_WIDGET(clientkey_file), 18);
	gtk_grid_attach(GTK_GRID(grid), clientkey_file, 1, grid_row, 2, 1);
	grid_row++;

	/* Buttons, ok and cancel */
	bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
	gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_EDGE);
	gtk_box_set_spacing (GTK_BOX (bbox), 40);
	gtk_widget_set_margin_top (GTK_WIDGET(bbox), 9);
	gtk_widget_set_margin_bottom (GTK_WIDGET(bbox), 18);
	gtk_widget_set_margin_start (GTK_WIDGET(bbox), 18);
	gtk_widget_set_margin_end (GTK_WIDGET(bbox), 18);
	button_ok = gtk_button_new_with_label(_("_OK"));
	gtk_widget_set_can_default (button_ok, TRUE);

	gtk_button_set_use_underline(GTK_BUTTON(button_ok), TRUE);
	gtk_container_add (GTK_CONTAINER (bbox), button_ok);
	/* Buttons, ok and cancel */
	button_cancel = gtk_button_new_with_label(_("_Cancel"));
	gtk_button_set_use_underline(GTK_BUTTON(button_cancel), TRUE);
	gtk_container_add (GTK_CONTAINER (bbox), button_cancel);
	gtk_grid_attach(GTK_GRID(grid), bbox, 0, grid_row, 3, 1);
	/* Pack it into the panel */
	gtk_box_pack_start(GTK_BOX(mp), grid, TRUE, TRUE, 4);

	priv->response_callback = response_callback;
	priv->response_callback_data = response_callback_data;

	priv->w[REMMINA_MESSAGE_PANEL_CACERTFILE] = cacert_file;
	priv->w[REMMINA_MESSAGE_PANEL_CACRLFILE] = cacrl_file;
	priv->w[REMMINA_MESSAGE_PANEL_CLIENTCERTFILE] = clientcert_file;
	priv->w[REMMINA_MESSAGE_PANEL_CLIENTKEYFILE] = clientkey_file;
	priv->w[REMMINA_MESSAGE_PANEL_BUTTONTOFOCUS] = button_ok;

	g_object_set_data(G_OBJECT(button_cancel), btn_response_key, (void *)GTK_RESPONSE_CANCEL);
	g_signal_connect(G_OBJECT(button_cancel), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
	g_object_set_data(G_OBJECT(button_ok), btn_response_key, (void *)GTK_RESPONSE_OK);
	g_signal_connect(G_OBJECT(button_ok), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);

}

void remmina_message_panel_focus_auth_entry(RemminaMessagePanel *mp)
{
	TRACE_CALL(__func__);

	RemminaMessagePanelPrivate *priv;
	GtkWidget *w;
	const gchar *username;

	if (mp == NULL)
		return;
	priv = remmina_message_panel_get_instance_private(mp);

	/* Activate default button */
	w = priv->w[REMMINA_MESSAGE_PANEL_BUTTONTOFOCUS];
	if (w && G_TYPE_CHECK_INSTANCE_TYPE(w, gtk_button_get_type()))
		gtk_widget_grab_default(w);

	w = priv->w[REMMINA_MESSAGE_PANEL_USERNAME];
	if (w == NULL)
	{
		w = priv->w[REMMINA_MESSAGE_PANEL_PASSWORD];
	}else {
		username = gtk_entry_get_text(GTK_ENTRY(w));
		if (username[0] != 0)
			w = priv->w[REMMINA_MESSAGE_PANEL_PASSWORD];
	}
	if (w == NULL)
		return;

	if (!G_TYPE_CHECK_INSTANCE_TYPE(w, gtk_entry_get_type()))
		return;

	gtk_widget_grab_focus(w);
}

void remmina_message_panel_field_set_string(RemminaMessagePanel *mp, int entryid, const gchar *text)
{
	RemminaMessagePanelPrivate *priv;

	if (mp == NULL)
		return;
	priv = remmina_message_panel_get_instance_private(mp);

	if (priv->w[entryid] == NULL)
		return;
	if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_entry_get_type()))
		return;

	gtk_entry_set_text(GTK_ENTRY(priv->w[entryid]), text != NULL ? text : "");
}

gchar* remmina_message_panel_field_get_string(RemminaMessagePanel *mp, int entryid)
{
	TRACE_CALL(__func__);

	RemminaMessagePanelPrivate *priv;

	if (mp == NULL)
		return NULL;
	priv = remmina_message_panel_get_instance_private(mp);

	if (priv->w[entryid] == NULL)
		return NULL;
	if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_entry_get_type()))
		return NULL;

	return g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->w[entryid])));
}

void remmina_message_panel_field_set_switch(RemminaMessagePanel *mp, int entryid, gboolean state)
{
	TRACE_CALL(__func__);

	RemminaMessagePanelPrivate *priv;

	if (mp == NULL)
		return;
	priv = remmina_message_panel_get_instance_private(mp);

	if (priv->w[entryid] == NULL)
		return;
	if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_switch_get_type()))
		return;

	gtk_switch_set_state(GTK_SWITCH(priv->w[entryid]), state);
}

gboolean remmina_message_panel_field_get_switch_state(RemminaMessagePanel *mp, int entryid)
{
	TRACE_CALL(__func__);

	RemminaMessagePanelPrivate *priv;

	if (mp == NULL)
		return FALSE;
	priv = remmina_message_panel_get_instance_private(mp);

	if (priv->w[entryid] == NULL)
		return FALSE;
	if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_switch_get_type()))
		return FALSE;

	return gtk_switch_get_state(GTK_SWITCH(priv->w[entryid]));
}


void remmina_message_panel_field_set_filename(RemminaMessagePanel *mp, int entryid, const gchar *filename)
{
	TRACE_CALL(__func__);

	RemminaMessagePanelPrivate *priv;

	if (mp == NULL)
		return;
	priv = remmina_message_panel_get_instance_private(mp);
	if (priv->w[entryid] == NULL)
		return;
	if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_file_chooser_button_get_type()))
		return;

	gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->w[entryid]), filename);
}

gchar* remmina_message_panel_field_get_filename(RemminaMessagePanel *mp, int entryid)
{
	TRACE_CALL(__func__);

	RemminaMessagePanelPrivate *priv;

	if (mp == NULL)
		return NULL;
	priv = remmina_message_panel_get_instance_private(mp);

	if (priv->w[entryid] == NULL)
		return NULL;
	if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_file_chooser_button_get_type()))
		return NULL;

	return gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(priv->w[entryid]));
}

void remmina_message_panel_response(RemminaMessagePanel *mp, gint response_id)
{
	g_signal_emit(mp, messagepanel_signals[RESPONSE], 0, response_id);
}

