/* $Id$ */
static char const _copyright[] =
"Copyright © 2015-2020 Pierre Pronchery <khorben@defora.org>";
/* This file is part of DeforaOS Desktop Coder */
static char const _license[] =
"This program is free software: you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
"the Free Software Foundation, version 3 of the License.\n"
"\n"
"This program is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
"GNU General Public License for more details.\n"
"\n"
"You should have received a copy of the GNU General Public License\n"
"along with this program.  If not, see <http://www.gnu.org/licenses/>.";



#include <stdio.h>
#include <Desktop.h>
#include "../config.h"

#ifndef PROGNAME_CONSOLE
# define PROGNAME_CONSOLE	"console"
#endif
#ifndef PROGNAME_PHP
# define PROGNAME_PHP	"php"
#endif
#ifndef PREFIX
# define PREFIX		"/usr/local"
#endif
#ifndef BINDIR
# define BINDIR		PREFIX "/bin"
#endif


/* private */
/* types */
typedef struct _Console
{
	GtkWidget * window;
	GtkWidget * code;
	GtkWidget * console;
} Console;


/* constants */
static char const * _authors[] =
{
	"Pierre Pronchery <khorben@defora.org>",
	NULL
};


/* prototypes */
static int _console(void);


/* functions */
/* console */
/* callbacks */
static void _console_on_about(gpointer data);
static void _console_on_clear(gpointer data);
static void _console_on_close(gpointer data);
static gboolean _console_on_closex(gpointer data);
static void _console_on_execute(gpointer data);
static void _execute_php(Console * console, char * text);

static int _console(void)
{
	/* FIXME allocate dynamically */
	static Console console;
	PangoFontDescription * desc;
	GtkWidget * vbox;
	GtkWidget * menuitem;
	GtkWidget * menu;
	GtkToolItem * toolitem;
	GtkWidget * paned;
	GtkWidget * widget;

	desc = pango_font_description_new();
	pango_font_description_set_family(desc, "Monospace");
	console.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_default_size(GTK_WINDOW(console.window), 400, 300);
	gtk_window_set_title(GTK_WINDOW(console.window), "PHP Console");
	g_signal_connect_swapped(console.window, "delete-event",
			G_CALLBACK(_console_on_closex), NULL);
	vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
	/* menu bar */
	widget = gtk_menu_bar_new();
	/* menu bar: file */
	menuitem = gtk_menu_item_new_with_mnemonic("_File");
	gtk_menu_shell_append(GTK_MENU_SHELL(widget), menuitem);
	menu = gtk_menu_new();
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
	menuitem = gtk_menu_item_new_with_mnemonic("_Run");
	g_signal_connect_swapped(menuitem, "activate",
			G_CALLBACK(_console_on_execute), &console);
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
	menuitem = gtk_separator_menu_item_new();
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
	menuitem = gtk_menu_item_new_with_mnemonic("C_lear");
	g_signal_connect_swapped(menuitem, "activate",
			G_CALLBACK(_console_on_clear), &console);
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
	menuitem = gtk_separator_menu_item_new();
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
	menuitem = gtk_menu_item_new_with_mnemonic("_Close");
	g_signal_connect_swapped(menuitem, "activate",
			G_CALLBACK(_console_on_close), NULL);
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
	/* menu bar: help */
	menuitem = gtk_menu_item_new_with_mnemonic("_Help");
	gtk_menu_shell_append(GTK_MENU_SHELL(widget), menuitem);
	menu = gtk_menu_new();
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
	menuitem = gtk_menu_item_new_with_mnemonic("_About");
	g_signal_connect_swapped(menuitem, "activate",
			G_CALLBACK(_console_on_about), &console);
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
	gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, TRUE, 0);
	/* toolbar */
	widget = gtk_toolbar_new();
	toolitem = gtk_tool_button_new_from_stock(GTK_STOCK_EXECUTE);
	g_signal_connect_swapped(toolitem, "clicked",
			G_CALLBACK(_console_on_execute), &console);
	gtk_toolbar_insert(GTK_TOOLBAR(widget), toolitem, -1);
	toolitem = gtk_tool_button_new_from_stock(GTK_STOCK_CLEAR);
	g_signal_connect_swapped(toolitem, "clicked",
			G_CALLBACK(_console_on_clear), &console);
	gtk_toolbar_insert(GTK_TOOLBAR(widget), toolitem, -1);
	gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, TRUE, 0);
	/* paned */
	paned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
	widget = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget),
			GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	console.code = gtk_text_view_new();
	gtk_widget_override_font(console.code, desc);
	gtk_container_add(GTK_CONTAINER(widget), console.code);
	gtk_paned_add1(GTK_PANED(paned), widget);
	widget = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget),
			GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	console.console = gtk_text_view_new();
	gtk_widget_override_font(console.console, desc);
	gtk_text_view_set_editable(GTK_TEXT_VIEW(console.console), FALSE);
	gtk_container_add(GTK_CONTAINER(widget), console.console);
	gtk_paned_add2(GTK_PANED(paned), widget);
	gtk_paned_set_position(GTK_PANED(paned), 150);
	gtk_box_pack_start(GTK_BOX(vbox), paned, TRUE, TRUE, 0);
	/* statusbar */
	widget = gtk_statusbar_new();
	gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, TRUE, 0);
	gtk_container_add(GTK_CONTAINER(console.window), vbox);
	gtk_widget_show_all(console.window);
	return 0;
}

/* callbacks */
static void _console_on_about(gpointer data)
{
	Console * console = data;
	GtkWidget * dialog;

	dialog = desktop_about_dialog_new();
	gtk_window_set_transient_for(GTK_WINDOW(dialog),
			GTK_WINDOW(console->window));
	desktop_about_dialog_set_authors(dialog, _authors);
	desktop_about_dialog_set_comments(dialog,
			"PHP console for the DeforaOS desktop");
	desktop_about_dialog_set_copyright(dialog, _copyright);
	desktop_about_dialog_set_license(dialog, _license);
	desktop_about_dialog_set_name(dialog, "Console");
	desktop_about_dialog_set_version(dialog, VERSION);
	desktop_about_dialog_set_website(dialog, "https://www.defora.org/");
	gtk_dialog_run(GTK_DIALOG(dialog));
	gtk_widget_destroy(dialog);
}

static void _console_on_clear(gpointer data)
{
	Console * console = data;
	GtkTextBuffer * tbuf;

	tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(console->console));
	gtk_text_buffer_set_text(tbuf, "", 0);
}

static void _console_on_close(gpointer data)
{
	_console_on_closex(data);
}

static gboolean _console_on_closex(gpointer data)
{
	(void) data;

	gtk_main_quit();
	return FALSE;
}

static void _console_on_execute(gpointer data)
{
	Console * console = data;
	GtkTextBuffer * tbuf;
	GtkTextIter start;
	GtkTextIter end;
	gchar * text;

	/* obtain the code */
	tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(console->code));
	gtk_text_buffer_get_start_iter(tbuf, &start);
	gtk_text_buffer_get_end_iter(tbuf, &end);
	text = gtk_text_buffer_get_text(tbuf, &start, &end, FALSE);
	_execute_php(console, text);
	g_free(text);
}

static void _execute_php(Console * console, char * text)
{
	const unsigned int flags = G_SPAWN_FILE_AND_ARGV_ZERO;
	char * argv[] = { BINDIR "/" PROGNAME_PHP, PROGNAME_PHP, "-r", NULL,
		NULL };
	gchar * output = NULL;
	int status;
	GError * error = NULL;
	GtkTextBuffer * tbuf;
	GtkTextIter end;

	argv[3] = text;
	/* FIXME implement asynchronously */
	if(g_spawn_sync(NULL, argv, NULL, flags, NULL, NULL, &output, NULL,
				&status, &error) == FALSE)
	{
		fprintf(stderr, "%s: %s (status: %d)\n", PROGNAME_CONSOLE,
				error->message, status);
		g_error_free(error);
		return;
	}
	/* append the output */
	tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(console->console));
	gtk_text_buffer_get_end_iter(tbuf, &end);
	gtk_text_buffer_insert(tbuf, &end, output, -1);
	g_free(output);
}


/* public */
/* main */
int main(int argc, char * argv[])
{
	int ret;

	gtk_init(&argc, &argv);
	ret = _console();
	gtk_main();
	return (ret == 0) ? 0 : 2;
}
