/* X-Chat
 * Copyright (C) 1998 Peter Zelezny.
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "../common/xchat.h"
#include "../common/fe.h"
#include "fe-gtk.h"
#include "gtkutil.h"
#include "pixmaps.h"
#include "xtext.h"
#include <gdk/gdkx.h>
#include <gtk/gtkinvisible.h>
#ifdef USE_GDK_PIXBUF
#include <gdk-pixbuf/gdk-pixbuf.h>
#endif
#ifdef USE_PANEL
#include <applet-widget.h>
extern int nopanel;
#endif

GdkFont *font_normal;
GdkFont *dialog_font_normal;

GtkWidget *proxy_invisible;

extern GtkStyle *redtab_style;
extern GtkStyle *bluetab_style;
extern GtkStyle *inputgad_style;
GdkPixmap *channelwin_pix;
GdkPixmap *dialogwin_pix;

extern int auto_connect;
extern char *xdir;
extern struct session *current_tab;
extern struct xchatprefs prefs;
extern GSList *sess_list;
extern GSList *serv_list;
extern GdkColor colors[];

extern int is_session (session * sess);
extern char *get_cpu_str (int color);
extern void userlist_hide (GtkWidget * igad, struct session *sess);
extern void PrintTextRaw (GtkWidget * textwidget, unsigned char *text);
extern void notify_gui_update (void);
extern void update_all_of (char *name);
extern void my_gtk_entry_set_text (GtkWidget * wid, char *text,
											  struct session *sess);
extern void palette_load (void);
extern void palette_save (void);
extern void key_init (void);
extern void create_window (struct session *);
extern void PrintText (struct session *, char *);
extern void url_autosave (void);
extern void open_server_list (GtkWidget *wid, gpointer sess, int dontshow);
extern void serverlist_autoconnect (struct session *sess, int);
extern void tree_blue_style (struct session *);
extern void tree_red_style (struct session *);
extern void menu_newshell_set_palette (session *sess);
extern Window get_desktop_window (Window the_window);


static void redraw_trans_xtexts (void)
{
	GSList *list = sess_list;
	struct session *sess;
	while (list)
	{
		sess = (struct session *) list->data;
#ifdef USE_ZVT
		if (sess->is_shell)
		{
			menu_newshell_set_palette (sess);
			gtk_widget_queue_draw (sess->gui->textgad);
		} else
#endif
			if (GTK_XTEXT (sess->gui->textgad)->transparent)
				gtk_xtext_refresh (GTK_XTEXT (sess->gui->textgad), 1);
		list = list->next;
	}
}

static gboolean handle_property_notify (GtkWidget *widget,
										GdkEventProperty *event,
										gpointer user_data)
{
	static Atom prop = None;

	if (prop == None)
		prop = XInternAtom (GDK_DISPLAY (), "_XROOTPMAP_ID", True);

	if (event->atom == prop)
		redraw_trans_xtexts ();

	return FALSE;
}

int
fe_args (int argc, char *argv[])
{
#ifdef USE_GNOME
	struct poptOption options[] = {
		{"cfgdir", 'd', POPT_ARG_STRING, 0, 0, "Config dir", 0},
		{"noauto", 'a', POPT_ARG_NONE, 0, 0, "Don't Auto connect", 0},
#ifdef USE_PANEL
		{"no-panel", 'n', POPT_ARG_NONE, 0, 0, "Don't use GNOME Panel", 0},
#endif
		POPT_AUTOHELP {0, '\0', 0, 0}
	};
#endif

	if (argc > 1)
	{
		if (!strcasecmp (argv[1], "-a") || !strcasecmp (argv[1], "--noauto"))
		{
			auto_connect = 0;
		}
#ifdef USE_PANEL
		if (!strcasecmp (argv[1], "-n") || !strcasecmp (argv[1], "--no-panel"))
		{
			nopanel = TRUE;
		}
#endif
		if (!strcasecmp (argv[1], "-v") || !strcasecmp (argv[1], "--version"))
		{
			puts (PACKAGE" "VERSION);
			return 0;
		}
#ifndef USE_GNOME
#ifdef ENABLE_NLS
		bindtextdomain (PACKAGE, PREFIX"/share/locale");
		textdomain (PACKAGE);
#endif
		if (!strcasecmp (argv[1], "-h") || !strcasecmp (argv[1], "--help"))
		{
			puts (PACKAGE" "VERSION" Options:\n\n"
					"   --cfgdir <dir> -d\t : use a different config dir\n"
					"   --noauto       -a\t : don't auto connect\n"
					"   --version      -v\t : show version information\n");
			return 0;
		}
#endif
	}
#ifdef ENABLE_NLS
#ifdef USE_GNOME
	bindtextdomain (PACKAGE, PREFIX"/share/locale");
	textdomain (PACKAGE);
#endif
#endif

	if (argc > 2)
	{
		if (!strcasecmp (argv[1], "-d") || !strcasecmp (argv[1], "--cfgdir"))
		{
			xdir = strdup (argv[2]);
			if (xdir[strlen (xdir) - 1] == '/')
				xdir[strlen (xdir) - 1] = 0;
		}
	}

#ifndef USE_GNOME
	gtk_set_locale ();
#endif

#ifdef USE_PANEL
	if (nopanel)
		gnome_init_with_popt_table (argv[0], VERSION, argc, argv, options, 0, 0);
	else
		applet_widget_init (argv[0], VERSION, argc, argv, options, 0, 0);
#else
#ifdef USE_GNOME
	gnome_init_with_popt_table (argv[0], VERSION, argc, argv, options, 0, 0);
#else
	gtk_init (&argc, &argv);
#endif
#endif

#ifndef USE_GNOME
#ifdef USE_GDK_PIXBUF
	gdk_rgb_init();
#endif
#endif

	proxy_invisible = gtk_invisible_new ();
	gtk_widget_show (proxy_invisible);

	/* Make the root window send events to the invisible proxy widget */
	gdk_window_set_user_data (GDK_ROOT_PARENT (), proxy_invisible);
	
	/* Select for PropertyNotify events from the root window */
	XSelectInput (GDK_DISPLAY (), GDK_ROOT_WINDOW (), PropertyChangeMask);

	gtk_signal_connect(GTK_OBJECT(proxy_invisible), "property-notify-event", GTK_SIGNAL_FUNC(handle_property_notify), NULL);

	return 1;
}

GdkFont *
my_font_load (char *fontname)
{
	GdkFont *font;
	char temp[256];

	if (!*fontname)
		fontname = "fixed";
	if (prefs.use_fontset)
		font = gdk_fontset_load (fontname);
	else
		font = gdk_font_load (fontname);
	if (!font)
	{
		snprintf (temp, 255, "Cannot open font:\n\n%s", fontname);
		gtkutil_simpledialog (temp);
		font = gdk_font_load ("fixed");
		if (!font)
		{
			g_error ("gdk_font_load failed");
			gtk_exit (0);
		}
	}
	return font;
}

static GtkStyle *
create_inputgad_style (void)
{
	GtkStyle *style;

	style = gtk_style_new ();

	gdk_font_unref (style->font);
	gdk_font_ref (font_normal);
	style->font = font_normal;

	style->base[GTK_STATE_NORMAL] = colors[19];
	style->bg[GTK_STATE_NORMAL] = colors[19];
	style->fg[GTK_STATE_NORMAL] = colors[18];

	return style;
}

void
fe_init (void)
{
	font_normal = my_font_load (prefs.font_normal);
	dialog_font_normal = my_font_load (prefs.dialog_font_normal);

	palette_load ();
	key_init ();
	pixmaps_init ();

	channelwin_pix = pixmap_load_from_file_with_msg (prefs.background);
	dialogwin_pix = pixmap_load_from_file_with_msg (prefs.background_dialog);
	inputgad_style = create_inputgad_style ();
}

static int done_intro = 0;

static void
init_sess (void)
{
	char buf[512];
	time_t tim = time (0);
	struct session *sess = sess_list->data;

	if (done_intro)
		return;
	done_intro = 1;

	if (auto_connect)
	{
		open_server_list (0, sess, prefs.skipserverlist);
		serverlist_autoconnect (sess, prefs.skipserverlist);
	} else
	{
		if (!prefs.skipserverlist)
			open_server_list (0, sess, 0);
	}
	snprintf (buf, sizeof buf,	
				"\n\n"
				" \037\0031                                                  \n"
				" \037\0038,2·                xchat "VERSION" dEVEL!              ·\n"
				"\n"
				"\0033  GTK/X Version\0032..\0035:\017 %d.%d.%d / %d (%d.%d)\n"
				"\0033  System Type\0032....\0035:\017 %s\n"
				"\0033  Launch Time\0032....\0035:\017 %.19s\n"
				"\0033  Binary Date\0032....\0035:\017 "__DATE__"\n"
				"\0033  Current Pid\0032....\0035:\017 %d\n"
				"\0033  Unix Username\0032..\0035:\017 %s\n"
				"\0033  Your UserId\0032....\0035:\017 %d\n",
					gtk_major_version, gtk_minor_version, gtk_micro_version,
					VendorRelease (GDK_DISPLAY ()),
					ProtocolVersion (GDK_DISPLAY ()),
					ProtocolRevision (GDK_DISPLAY ()),
					get_cpu_str (1), ctime (&tim), getpid (), g_get_user_name (),
					getuid ()
				 );
	PrintText (sess, buf);

	strcpy (buf, "\0033  Features\0032.......\0035: \017");
#ifdef USE_GDK_PIXBUF
	strcat (buf, "Gdk-Pixbuf ");
#endif
#ifdef USE_GNOME
	strcat (buf, "Gnome ");
#endif
#ifdef USE_ZVT
	strcat (buf, "Zvt ");
#endif
#ifdef USE_PANEL
	strcat (buf, "Panel ");
#endif
#ifdef USE_PERL
	strcat (buf, "Perl ");
#endif
#ifdef USE_PYTHON
	strcat (buf, "Python ");
#endif
#ifdef USE_PLUGIN
	strcat (buf, "Plugin ");
#endif
#ifdef ENABLE_NLS
	strcat (buf, "NLS ");
#endif
#ifdef USE_TRANS
	strcat (buf, "Trans ");
#endif
#ifdef USE_HEBREW
	strcat (buf, "Hebrew ");
#endif
#ifdef USE_OPENSSL
	strcat (buf, "OpenSSL ");
#endif
#ifdef SOCKS
	strcat (buf, "Socks5\n\n");
#else
	strcat (buf, "\n\n");
#endif
	PrintText (sess, buf);
	if (getuid () == 0)
	{
		PrintText (sess, "\nYour move root!\n");
	}
	while (gtk_events_pending ())
		gtk_main_iteration ();
}

void
fe_main (void)
{
#ifdef USE_PANEL
	if (nopanel)
		gtk_main ();
	else
		applet_widget_gtk_main ();
#else
	gtk_main ();
#endif
}

void
fe_cleanup (void)
{
	palette_save ();

	if (prefs.autosave_url)
		url_autosave ();
}

void
fe_exit (void)
{
	gtk_main_quit ();
}

int
fe_timeout_add (int interval, void *callback, void *userdata)
{
	return gtk_timeout_add (interval, (GtkFunction) callback, userdata);
}

void
fe_timeout_remove (int tag)
{
	gtk_timeout_remove (tag);
}

void
fe_new_window (struct session *sess)
{
	sess->gui = malloc (sizeof (struct session_gui));
	memset (sess->gui, 0, sizeof (struct session_gui));
	create_window (sess);
	init_sess ();
}

void
fe_new_server (struct server *serv)
{
	serv->gui = malloc (sizeof (struct server_gui));
	memset (serv->gui, 0, sizeof (struct server_gui));
}

void
fe_message (char *msg, int wait)
{
	GtkWidget *dialog;

	dialog = gtkutil_simpledialog (msg);
	if (wait)
	{
		gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
								  gtkutil_null_this_var, &dialog);
		while (dialog)
			gtk_main_iteration ();
	}
}

void
fe_input_remove (int tag)
{
	gdk_input_remove (tag);
}

int
fe_input_add (int sok, int read, int write, int ex, void *func, void *data)
{
	int type = 0;

	if (read)
		type |= GDK_INPUT_READ;
	if (write)
		type |= GDK_INPUT_WRITE;
	if (ex)
		type |= GDK_INPUT_EXCEPTION;

	return gdk_input_add (sok, type, func, data);
}

void
fe_set_topic (struct session *sess, char *topic)
{
	gtk_entry_set_text (GTK_ENTRY (sess->gui->topicgad), topic);
}

void
fe_set_hilight (struct session *sess)
{
#ifdef USE_PANEL
	if (sess->gui->panel_button)
		gtk_widget_set_style (GTK_BIN (sess->gui->panel_button)->child,
									 bluetab_style);
#endif
	gtk_widget_set_style (sess->gui->changad, bluetab_style);
	if (prefs.treeview)
		tree_blue_style (sess);
}

void
fe_update_channel_key (struct session *sess)
{
	my_gtk_entry_set_text (sess->gui->key_entry, sess->channelkey, sess);

	fe_set_title (sess);
}

void
fe_update_channel_limit (struct session *sess)
{
	char tmp[16];
	sprintf (tmp, "%d", sess->limit);
	my_gtk_entry_set_text (sess->gui->limit_entry, tmp, sess);
}

int
fe_is_chanwindow (struct server *serv)
{
	if (!serv->gui->chanlist_window)
		return 0;
	return 1;
}

void
fe_chan_list_end (struct server *serv)
{
	gtk_widget_set_sensitive (serv->gui->chanlist_refresh, TRUE);
}

void
fe_notify_update (char *name)
{
	if (name)
		update_all_of (name);
	else
		notify_gui_update ();
}

void
fe_text_clear (struct session *sess)
{
	GtkXText *xtext = (GtkXText *)sess->gui->textgad;
	gtk_xtext_remove_lines (xtext, -1, TRUE);
	if (xtext->auto_indent)
		xtext->indent = 1;
}

void
fe_close_window (struct session *sess)
{
	gtk_widget_destroy (sess->gui->window);
}

static int
updatedate_bar (struct session *sess)
{
	static int type = 0;
	static float pos = 0;

	if (!is_session (sess))
		return 0;

	pos += 0.05;
	if (pos >= 0.99)
	{
		if (type == 0)
		{
			type = 1;
			gtk_progress_bar_set_orientation ((GtkProgressBar *) sess->gui->bar,
														 GTK_PROGRESS_RIGHT_TO_LEFT);
		} else
		{
			type = 0;
			gtk_progress_bar_set_orientation ((GtkProgressBar *) sess->gui->bar,
														 GTK_PROGRESS_LEFT_TO_RIGHT);
		}
		pos = 0.05;
	}
	gtk_progress_bar_update ((GtkProgressBar *) sess->gui->bar, pos);
	return 1;
}

void
fe_progressbar_start (struct session *sess)
{
	if (sess->gui->op_box)
	{
		sess->gui->bar = gtk_progress_bar_new ();
		gtk_box_pack_start (GTK_BOX (sess->gui->op_box), sess->gui->bar, 0, 0,
								  0);
		gtk_widget_show (sess->gui->bar);
		sess->server->bartag =
			gtk_timeout_add (50, (GtkFunction) updatedate_bar, sess);
	}
}

void
fe_progressbar_end (struct session *sess)
{
	struct server *serv;
	GSList *list = sess_list;

	if (sess)
	{
		serv = sess->server;
		while (list)				  /* check all windows that use this server and  *
										   * remove the connecting graph, if it has one. */
		{
			sess = (struct session *) list->data;
			if (sess->server == serv && sess->gui->bar)
			{
				if (GTK_IS_WIDGET (sess->gui->bar))
					gtk_widget_destroy (sess->gui->bar);
				sess->gui->bar = 0;
				gtk_timeout_remove (sess->server->bartag);
			}
			list = list->next;
		}
	}
}

void
fe_print_text (struct session *sess, char *text)
{
	PrintTextRaw (sess->gui->textgad, text);

	if (prefs.limitedtabhighlight && !sess->highlight_tab)
		return;

	sess->highlight_tab = FALSE;

	if (!sess->new_data && !sess->nick_said && sess != current_tab)
	{
#ifdef USE_PANEL

		if (sess->gui->panel_button)
			gtk_widget_set_style (GTK_BIN (sess->gui->panel_button)->child,
										 redtab_style);
#endif
		if (prefs.treeview)
			tree_red_style (sess);
	}

	if (!sess->new_data && sess != current_tab &&
		 sess->is_tab && !sess->nick_said)
	{
		sess->new_data = TRUE;
		gtk_widget_set_style (sess->gui->changad, redtab_style);
	}
}

void
fe_beep (void)
{
	gdk_beep ();
}

int
fe_is_confmode (struct session *sess)
{
	if (GTK_TOGGLE_BUTTON (sess->gui->confbutton)->active)
		return 1;
	return 0;
}

void
fe_userlist_hide (struct session *sess)
{
	userlist_hide (0, sess);
}

char *
fe_buffer_get (session * sess)
{
	return gtk_xtext_get_chars (GTK_XTEXT (sess->gui->textgad));
}

void
fe_set_lag (server *serv, int lag)
{
	GSList *list = sess_list;
	session *sess;
	gdouble per;

	per = (double)((double)lag / (double)40);
	if (per > 1.0)
		per = 1.0;

	while (list)
	{
		sess = list->data;
		if (sess->server == serv && sess->gui->lagometer)
		{
			gtk_progress_bar_update ((GtkProgressBar *) sess->gui->lagometer, per);
		}
		list = list->next;
	}
}
