#include <sys/stat.h>
#include <gtk/gtk.h>

#include "guiutils.h"
#include "csd.h"

#include "editor.h"
#include "editorcb.h"

#include "viewer.h"
#include "viewercb.h"
#include "viewerfio.h"

#include "pref.h"
#include "prefop.h"

#include "manedit.h"


void PrefDoApply(pref_struct *pref);
void PrefDoFetch(pref_struct *pref);


/*
 *	Procedure to set values on preferences window to its core
 *	structure windows and resources.
 */
void PrefDoApply(pref_struct *pref)
{
	gint i;
	GtkWidget *w;
	gboolean pref_syntax_highlighting;
	GtkStyle *style_ptr;
	gchar *font_name;
	GdkColormap *colormap;
	editor_struct *editor;
	viewer_struct *viewer;
	medit_core_struct *core_ptr;
	medit_styles_list_struct *styles_list;

	if(pref == NULL)
	    return;

	core_ptr = (medit_core_struct *)pref->core_ptr;
	if(core_ptr == NULL)
	    return;

	/* Get some current values from pref */

	/* Syntax highlighting */
	pref_syntax_highlighting = PrefParmGetValueB(
	    pref, MEDIT_PREF_PARM_EDITOR_ENABLE_SYNHL
	);


	/* Styles list */
	styles_list = &core_ptr->styles_list;

	/* Get colors, each widget for containing color information
	 * is a GtkDrawingArea with an allocated csd_color_struct
	 * set as its object data
	 */
/* Macro to get csd_color_struct from the widget w (which is a
 * GtkDrawingArea) and allocate a GdkColor and set the widget w's
 * background color to it and clear the widget's window. Also updates
 * the style_ptr's foreground color
 */
#define DO_APPLY_DA_COLOR_FG				\
if(((w != NULL) ? !GTK_WIDGET_NO_WINDOW(w) : FALSE) &&	\
   (style_ptr != NULL)					\
) {							\
 GdkColor gdk_color;					\
 csd_color_struct *color_ptr = (csd_color_struct *)	\
  gtk_object_get_user_data(GTK_OBJECT(w));		\
							\
 colormap = gdk_window_get_colormap(w->window);		\
							\
 gdk_color.red = (guint16)(color_ptr->r * 65535.0);	\
 gdk_color.green = (guint16)(color_ptr->g * 65535.0);	\
 gdk_color.blue = (guint16)(color_ptr->b * 65535.0);	\
							\
 /* Update style foreground color */			\
 style_ptr->fg[GTK_STATE_NORMAL] = gdk_color;		\
}

#define DO_APPLY_DA_COLOR_BASE				\
if(((w != NULL) ? !GTK_WIDGET_NO_WINDOW(w) : FALSE) &&	\
   (style_ptr != NULL)					\
) {							\
 GdkColor gdk_color;					\
 csd_color_struct *color_ptr = (csd_color_struct *)	\
  gtk_object_get_user_data(GTK_OBJECT(w));		\
							\
 colormap = gdk_window_get_colormap(w->window);		\
							\
 gdk_color.red = (guint16)(color_ptr->r * 65535.0);	\
 gdk_color.green = (guint16)(color_ptr->g * 65535.0);	\
 gdk_color.blue = (guint16)(color_ptr->b * 65535.0);	\
							\
 /* Update style background color */			\
 style_ptr->base[GTK_STATE_NORMAL] = gdk_color;		\
}

	/* Edit text standard color */
	w = PrefParmGetWidget(pref, MEDIT_PREF_PARM_COLOR_EDIT_TEXT_FG);
	style_ptr = styles_list->edit_text_standard;
	DO_APPLY_DA_COLOR_FG

	/* Edit text standard background color */
	w = PrefParmGetWidget(pref, MEDIT_PREF_PARM_COLOR_EDIT_TEXT_BG);
	style_ptr = styles_list->edit_text_background;
	DO_APPLY_DA_COLOR_BASE

	/* Edit text XML deliminator color */
	w = PrefParmGetWidget(pref, MEDIT_PREF_PARM_COLOR_EDIT_TEXT_DELIM);
	style_ptr = styles_list->edit_text_tag_deliminator;
	DO_APPLY_DA_COLOR_FG

	/* Edit text XML tag color */
	w = PrefParmGetWidget(pref, MEDIT_PREF_PARM_COLOR_EDIT_TEXT_TAG);
	style_ptr = styles_list->edit_text_tag_text;
	DO_APPLY_DA_COLOR_FG

	/* Edit text XML symbol alternate color */
	w = PrefParmGetWidget(pref, MEDIT_PREF_PARM_COLOR_EDIT_TEXT_SYMREP);
	style_ptr = styles_list->edit_text_tag_symrep;
	DO_APPLY_DA_COLOR_FG


	/* ManPage text normal foreground color */
	w = PrefParmGetWidget(pref, MEDIT_PREF_PARM_COLOR_MANPAGE_TEXT_FG);
	style_ptr = styles_list->manpage_text_standard;
	DO_APPLY_DA_COLOR_FG

	/* ManPage text normal background color */
	w = PrefParmGetWidget(pref, MEDIT_PREF_PARM_COLOR_MANPAGE_TEXT_BG);
	style_ptr = styles_list->manpage_text_background;
	DO_APPLY_DA_COLOR_BASE

	/* ManPage text bold foreground color */
	w = PrefParmGetWidget(pref, MEDIT_PREF_PARM_COLOR_MANPAGE_TEXT_BOLD);
	style_ptr = styles_list->manpage_text_bold;
	DO_APPLY_DA_COLOR_FG

	/* ManPage text underline foreground color */
	w = PrefParmGetWidget(pref, MEDIT_PREF_PARM_COLOR_MANPAGE_TEXT_UNDERLINE);
	style_ptr = styles_list->manpage_text_underline;
	DO_APPLY_DA_COLOR_FG

#undef DO_APPLY_DA_COLOR_FG
#undef DO_APPLY_DA_COLOR_BASE


/* Macro to unref the current font on the given style and load a new one
 * from the GtkEntry w value
 */
#define DO_APPLY_ENTRY_FONT_NAME {			\
if((font_name != NULL) && (style_ptr != NULL)) {	\
 if(style_ptr->font != NULL)				\
  gdk_font_unref(style_ptr->font);			\
 style_ptr->font = gdk_font_load(font_name);		\
} }

	/* Font editable text */
	font_name = (gchar *)PrefParmGetValueP(
	    pref, MEDIT_PREF_PARM_FONT_EDIT_STD
	);
	style_ptr = styles_list->edit_text_standard;
	DO_APPLY_ENTRY_FONT_NAME
	style_ptr = styles_list->edit_text_background;
	DO_APPLY_ENTRY_FONT_NAME
	style_ptr = styles_list->edit_text_tag_deliminator;
	DO_APPLY_ENTRY_FONT_NAME
	style_ptr = styles_list->edit_text_tag_text;
	DO_APPLY_ENTRY_FONT_NAME
	style_ptr = styles_list->edit_text_tag_symrep;
	DO_APPLY_ENTRY_FONT_NAME

	font_name = (gchar *)PrefParmGetValueP(
	    pref, MEDIT_PREF_PARM_FONT_MANPAGE_STD
	);
	style_ptr = styles_list->manpage_text_standard;
	DO_APPLY_ENTRY_FONT_NAME
	style_ptr = styles_list->manpage_text_background;
	DO_APPLY_ENTRY_FONT_NAME
	font_name = (gchar *)PrefParmGetValueP(
	    pref, MEDIT_PREF_PARM_FONT_MANPAGE_BOLD
	);
	style_ptr = styles_list->manpage_text_bold;
	DO_APPLY_ENTRY_FONT_NAME
	font_name = (gchar *)PrefParmGetValueP(
	    pref, MEDIT_PREF_PARM_FONT_MANPAGE_UNDERLINE
	);
	style_ptr = styles_list->manpage_text_underline;
	DO_APPLY_ENTRY_FONT_NAME



#undef DO_APPLY_ENTRY_FONT_NAME



	/* *********************************************************** */

	/* Go through each editor */
	for(i = 0; i < core_ptr->total_editors; i++)
	{
	    editor = core_ptr->editor[i];
	    if((editor == NULL) ? TRUE : !editor->initialized)
		continue;

	    if(editor->processing)
		continue;

	    /* Text widget colors */
	    w = editor->section_text;
	    if((w == NULL) ? 0 : !GTK_WIDGET_NO_WINDOW(w))
	    {
		GtkStyle *cur_style = gtk_widget_get_style(w);

		colormap = gdk_window_get_colormap(w->window);
		if(cur_style != NULL)
		{
		    /* Set new (base) color */
		    style_ptr = styles_list->edit_text_background;
		    if((style_ptr != NULL) && (colormap != NULL))
		    {
			cur_style->base[GTK_STATE_NORMAL] =
			    style_ptr->base[GTK_STATE_NORMAL];
			gdk_color_alloc(
			    colormap,
			    &cur_style->base[GTK_STATE_NORMAL]
			);
		    }

		    /* Set new font */
		    style_ptr = styles_list->edit_text_standard;
		    if(style_ptr != NULL)
		    {
			if(cur_style->font != NULL)
			    gdk_font_unref(cur_style->font);
			cur_style->font = style_ptr->font;
			if(cur_style->font != NULL)
			    gdk_font_ref(cur_style->font);
		    }
		}
		gtk_signal_emit_by_name(GTK_OBJECT(w), "style_set");
		gtk_widget_draw_default(w);
	    }

	    /* Tool tips */
	    if(PrefParmGetValueB(pref, MEDIT_PREF_PARM_TOOL_TIPS))
	    {


	    }
	    else
	    {


	    }

	    /* Syntax highlighting */
	    GUIMenuItemSetCheck(
		editor->syntax_highlight_cmi,
		pref_syntax_highlighting,
		FALSE
	    );

	    /* Note that this will cause any selected branch's values
	     * to be applied and then refetched, ensuring that the
	     * displayed values on the editor's text widgets reflect the
	     * new preference values
	     */
	    EditorManualSyntaxHighlightToggleCB(
		editor->syntax_highlight_cmi,
		(gpointer)editor
	    );


	    EditorUpdateMenus(editor);
	}

	/* Go through each viewer */
	for(i = 0; i < core_ptr->total_viewers; i++)
	{
	    viewer = core_ptr->viewer[i];
	    if((viewer == NULL) ? TRUE : !viewer->initialized)
		continue;

	    if(viewer->processing)
		continue;

	    /* Text widget colors */
	    w = viewer->view_text;
	    if((w != NULL) ? !GTK_WIDGET_NO_WINDOW(w) : FALSE)
	    {
		GtkStyle *cur_style = gtk_widget_get_style(w);  

		colormap = gdk_window_get_colormap(w->window);
		if(cur_style != NULL)
		{
		    /* Set new (base) color */
		    style_ptr = styles_list->manpage_text_background;
		    if((style_ptr != NULL) && (colormap != NULL))
		    {
			cur_style->base[GTK_STATE_NORMAL] =
			    style_ptr->base[GTK_STATE_NORMAL];
			gdk_color_alloc(
			    colormap,
			    &cur_style->base[GTK_STATE_NORMAL]
			);
		    }

		    /* Set new font */
		    style_ptr = styles_list->manpage_text_standard;
		    if(style_ptr != NULL)
		    {
			if(cur_style->font != NULL)
			    gdk_font_unref(cur_style->font);
			cur_style->font = style_ptr->font;
			if(cur_style->font != NULL)
			    gdk_font_ref(cur_style->font);
		    }
		}
		gtk_signal_emit_by_name(GTK_OBJECT(w), "style_set");
		gtk_widget_draw_default(w);
	    }


	    /* Need to make this viewer reload */
	    if(viewer->cur_manpage_path != NULL)
	    {
		struct stat stat_buf;

		/* Last opened manpage path exists? */
		if(!stat(viewer->cur_manpage_path, &stat_buf))
		{
		    /* Make a copy of the viewer's last opened manpage
		     * path
		     */
		    gchar *tmp_path = g_strdup(viewer->cur_manpage_path);
		    gchar *tmp_name = g_strdup(viewer->cur_manpage_path);

		    ViewerSetBusy(viewer);
		    ViewerViewTextRecordScrollPositions(viewer);
		    ViewerTextDelete(viewer, 0, -1);
		    ViewerTextInsertPosition(viewer, 0);
		    ViewerLoadFile(viewer, tmp_path, tmp_name);
		    ViewerSetReady(viewer);

		    /* Delete copy of last opened manpage path */
		    g_free(tmp_path);
		    g_free(tmp_name);
		}
	    }



	    ViewerUpdateMenus(viewer);
	}
}

/*
 *      Procedure to get values from the core structure's windows and
 *	store them on the preferences window structure.
 */
void PrefDoFetch(pref_struct *pref)
{
	gint i;
	GtkWidget *w;
	gboolean pref_syntax_highlighting;
	editor_struct *editor;
	medit_core_struct *core_ptr;
	if(pref == NULL)
	    return;

	core_ptr = (medit_core_struct *)pref->core_ptr;
	if(core_ptr == NULL)
	    return;

	/* Get some current values from pref */

	/* Syntax highlighting */
	pref_syntax_highlighting = PrefParmGetValueB(
	    pref, MEDIT_PREF_PARM_EDITOR_ENABLE_SYNHL
	);


	/* Go through each editor, fetching certain values.
	 * Note this will effectlvly result in the last indexed
	 * editor having precident values. However each editor should
	 * be iterated through
	 */
	for(i = 0; i < core_ptr->total_editors; i++)
	{
	    editor = core_ptr->editor[i];
	    if((editor == NULL) ? TRUE : !editor->initialized)
		continue;
   
	    if(editor->processing)
		continue;

	    /* Syntax highlighting */
	    pref_syntax_highlighting = GUIMenuItemGetCheck(
		editor->syntax_highlight_cmi
	    );
	}





	/* Update values to pref widgets */

	/* Syntax highlighting */
	w = PrefParmGetWidget(
	    pref, MEDIT_PREF_PARM_EDITOR_ENABLE_SYNHL
	);
	if((w != NULL) ? GTK_IS_TOGGLE_BUTTON((GtkObject *)w) : FALSE)
	{
	    GTK_TOGGLE_BUTTON(w)->active = pref_syntax_highlighting;
	}


}
