#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <gnome.h>
#include <errno.h>

#include "interface.h"
#include "support.h"

#include "main.h"
#include "trx.h"
#include "wf.h"
#include "snd.h"
#include "macro.h"
#include "prefs.h"
#include "ptt.h"
#include "syncscope.h"
#include "ascii.h"
#include "log.h"

GtkWidget *appwindow;
GtkWidget *PopupMenu;

gchar *SoftString = "gMFSK v" VERSION " (Gnome MFSK) by OH2BNS";

/* ---------------------------------------------------------------------- */

static gboolean error_idle_func(gpointer data)
{
	GtkWidget *dialog;
	gchar *msg = (gchar *) data;

	gdk_threads_enter();

	dialog = gnome_message_box_new(msg, GNOME_MESSAGE_BOX_ERROR,
					GNOME_STOCK_BUTTON_OK,
					NULL);
	gnome_dialog_run(GNOME_DIALOG(dialog));
	g_free(data);

	gdk_threads_leave();

	return FALSE;
}

void errmsg(const gchar *fmt, ...)
{
	va_list args;
	gchar *msg;

	va_start(args, fmt);
	msg = g_strdup_vprintf(fmt, args);
	va_end(args);

	g_idle_add(error_idle_func, (gpointer) msg);
}

void statusmsg(const char *fmt, ...)
{
	va_list args;
	gchar *msg;
	GnomeAppBar *appbar;

	va_start(args, fmt);
	msg = g_strdup_vprintf(fmt, args);
	va_end(args);

	appbar = GNOME_APPBAR(lookup_widget(appwindow, "appbar1"));
	gnome_appbar_set_status(appbar, msg);

	g_free(msg);
}

void push_button(const gchar *name)
{
	GtkToggleButton *button;

	button = GTK_TOGGLE_BUTTON(lookup_widget(appwindow, name));
	gtk_toggle_button_set_active(button, TRUE);
}

/* ---------------------------------------------------------------------- */

void send_char(const gchar c)
{
	GtkText *text;

	text = GTK_TEXT(lookup_widget(appwindow, "txtext"));

	gtk_text_backward_delete(text, 1);
	gtk_text_insert(text, NULL, NULL, NULL, &c, 1);
	gtk_text_insert(text, NULL, NULL, NULL, "_", -1);

	trx_put_tx_char(c);
}

void send_string(gchar *str)
{
	GtkText *text;

	text = GTK_TEXT(lookup_widget(appwindow, "txtext"));

	gtk_text_backward_delete(text, 1);
	gtk_text_insert(text, NULL, NULL, NULL, str, -1);
	gtk_text_insert(text, NULL, NULL, NULL, "_", -1);

	while (*str)
		trx_put_tx_char(*str++);
}

/* ---------------------------------------------------------------------- */

static gint main_loop(gpointer unused)
{
	static gint cr_flag = 0;
	GtkWidget *widget;
	GdkColor *colr;
	guchar bsdata[SYNCSCOPE_WIDTH];
	guchar *p;
	gint c;

	gdk_threads_enter();

	while ((c = trx_get_rx_char()) != -1) {
		if (c == 0)
			continue;

		/* CR-LF reduced to a single LF */
		if (cr_flag && c == 10) {
			cr_flag = 0;
			continue;
		} else if (c == 13)
			cr_flag = 1;

		widget = lookup_widget(appwindow, "rxtext");

		/* backspace is a special case */
		if (c == 8) {
			gtk_text_backward_delete(GTK_TEXT(widget), 1);
			log_to_file("<BS>");
			continue;
		}

		p = ascii[c];
		if (*p == '<' && c != '<')
			colr = &prefs.hl_color;
		else
			colr = &prefs.rx_color;
		gtk_text_insert(GTK_TEXT(widget), txfont, colr, NULL, p, -1);
		log_to_file(p);
	}

	while ((c = trx_get_echo_char()) != -1) {
		if (c == 0)
			continue;

		widget = lookup_widget(appwindow, "rxtext");

		/* backspace is a special case */
		if (c == 8) {
			gtk_text_backward_delete(GTK_TEXT(widget), 1);
			log_to_file("<BS>");
			continue;
		}

		p = ascii[c];
		colr = &prefs.tx_color;
		gtk_text_insert(GTK_TEXT(widget), rxfont, colr, NULL, p, -1);
		log_to_file(p);
	}

	widget = lookup_widget(appwindow, "metricdial");
	gtk_dial_set_value(GTK_DIAL(widget), trx_get_metric());

	widget = lookup_widget(appwindow, "freqspinbutton");
	if (!GTK_WIDGET_HAS_FOCUS(widget))
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), trx_get_freq());

	trx_get_syncscope(bsdata);
	syncscope_draw(bsdata);

	gdk_threads_leave();

	wf_run();

	return TRUE;
}

int main(int argc, char *argv[])
{
	GtkText *text;
	GtkStyle *style;
	GtkToggleButton *button;

	g_thread_init(NULL);
	gnome_init("gmfsk", VERSION, argc, argv);

	appwindow = create_appwindow();
	PopupMenu = create_popupmenu();

	load_config();
	macroconfig_load();

	init_ptt(prefs.pttdev, prefs.pttinv);
	init_wf(2048, 1000.0);

	/* draw the tx window "cursor" */
	text = GTK_TEXT(lookup_widget(appwindow, "txtext"));
	gtk_text_insert(text, NULL, NULL, NULL, "_", -1);

	/* set tx window font and bg color */
	style = gtk_widget_get_default_style();
	style = gtk_style_copy(style);
	style->font = txfont;
	style->base[GTK_STATE_NORMAL] = prefs.tx_win_color;
	gtk_widget_set_style(GTK_WIDGET(text), style);

	/* set word wrap on rx window */
	text = GTK_TEXT(lookup_widget(appwindow, "rxtext"));
	gtk_text_set_word_wrap(text, TRUE);

	/* set rx window bg color */
	style = gtk_widget_get_default_style();
	style = gtk_style_copy(style);
	style->base[GTK_STATE_NORMAL] = prefs.rx_win_color;
	gtk_widget_set_style(GTK_WIDGET(text), style);

	/* set AFC and SQUELCH */
	button = GTK_TOGGLE_BUTTON(lookup_widget(appwindow, "afcbutton"));
	gtk_toggle_button_set_active(button, prefs.afc);
	button = GTK_TOGGLE_BUTTON(lookup_widget(appwindow, "squelchbutton"));
	gtk_toggle_button_set_active(button, prefs.squelch);

	/* periodic task - draw waterfall */
	gtk_timeout_add(100, main_loop, NULL);

	/* show the main window */
	gtk_widget_show(appwindow);

	/* create the syncscope */
	syncscope_init();

	/* initialize the trx thread */
	trx_init();
	trx_set_freq(1000.0);

	/* let GTK do it's job */
	gdk_threads_enter();
	gtk_main();
	gdk_threads_leave();

	return 0;
}

