#include <stdio.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#include <X11/Xmd.h>

#include "aux_module.h"
#include "xaux_common.h"
#include "xaux_ext_common.h"

/* Define Aux class */
xaux_class_t *xc_ = 0;
int im_ = 0;
int ic_ = 0;

#define XAUX_MANAGER_CLASS_NAME  "com.sun.iiim.cle.aux.manager.gtk2"
#define ATOM_NUM_XAUX_MANAGER    32

/* Define Aux class */
xaux_class_t xaux_class = {
	XAUX_MANAGER_CLASS_NAME, 1,
	NULL,
	(Window)0, (Window)0, (Window)0,
	(Atom)0, (Atom)0, (Atom)0, (Atom)0,
	{ (Atom)0 }, ATOM_NUM_XAUX_MANAGER, 0,
	{ (Atom)0 }, ATOM_NUM_XAUX_MANAGER, 0,
	NULL,
};

/*  Auxiliary Window User Input Method Information  */
extern GtkWidget *_toolbar_window;

Display *gDisplay = NULL;
Window  gWindow  = 0;

void aux_manager_proc_le_notify(aux_ext_data_t *aux_ext_data);

/*   
	Event Handler 
*/
GdkFilterReturn xaux_ext_event_handler(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer user_data)
{
	XEvent *xevent = (XEvent *) gdk_xevent;

	switch (xevent->type) {
		case ClientMessage:
			xaux_ext_process_client_message((Display *)gDisplay,
				(XClientMessageEvent *) xevent);
			break;
		case SelectionClear:
			break;
	}
	return GDK_FILTER_CONTINUE;
}

/*
	xaux_ext_init_classes(): Initialize the Atom of Auxiliary Window.
	It is in ../xaux_common/xaux_ext_common.c
*/
int xaux_ext_register_classes(GdkWindow *window)
{
	char *locale;

	gDisplay = (Display *)GDK_WINDOW_XDISPLAY(window);
	gWindow  = (Window)GDK_WINDOW_XWINDOW(window);

	/* Register aux class */
	if (xaux_ext_init_classes(gDisplay, (xaux_class_t *)&xaux_class, gWindow) == False)
		return(False);

	aux_manager_register_aux_modules(gDisplay, gWindow);

	return(True);
}

/* 
Note:
     xaux_ext_Start(), xaux_ext_Draw(), xaux_ext_Done() 
     These three functions are all called by xaux_ext_process_client_message()

     xaux_ext_SetValue() will send auxiliary window information to language engine;
*/

/* Method - Start */
Bool xaux_ext_Start(xaux_class_t *xc, aux_ext_data_t *aux_ext_data, Atom atom)
{
	AuxModule aux_module = NULL;
	char *class_name = NULL;

	char *locale = NULL;
	int  locale_id;

	DEBUG_printf("ext_Start: im:%d, ic:%d\n", aux_ext_data->im, aux_ext_data->ic);
	DEBUG_printf("ext_Start: integer_count: %d, strings_count: %d\n", aux_ext_data->integer_count, aux_ext_data->string_count);
	im_ = aux_ext_data->im;
	ic_ = aux_ext_data->ic;
	xc_ = xc;

	class_name = XGetAtomName(gDisplay, atom);
	if (class_name == NULL)
		return False;

	DEBUG_printf("class_name: %s\n", class_name);
	aux_module = (AuxModule)aux_manager_get_module_by_classname(class_name);
	DEBUG_printf("aux_module: %p\n", aux_module);
	if (aux_module == NULL || aux_module->methods == NULL)
		return False;

	aux_module->methods->aux_module_Start(aux_ext_data);

	return True;
}

/* Method - Draw */
Bool xaux_ext_Draw(xaux_class_t *xc, aux_ext_data_t *aux_ext_data, Atom atom)
{
	AuxModule aux_module = NULL;
	char *class_name = NULL;

	DEBUG_printf("ext_Draw == im:0x%x, ic:0x%x\n",aux_ext_data->im, aux_ext_data->ic);
	DEBUG_printf("ext_Draw: integer_count: %d, strings_count: %d\n", aux_ext_data->integer_count, aux_ext_data->string_count);
	im_ = aux_ext_data->im;
	ic_ = aux_ext_data->ic;
	xc_ = xc;

	class_name = XGetAtomName(gDisplay, atom);
	if (class_name == NULL)
		return False;

	DEBUG_printf("class_name: %s\n", class_name);
	aux_module = (AuxModule)aux_manager_get_module_by_classname(class_name);
	DEBUG_printf("aux_module: %p\n", aux_module);
	if (aux_module == NULL || aux_module->methods == NULL)
		return False;

	aux_module->methods->aux_module_Draw(aux_ext_data);

	return True;
}

/* Method - Done */
Bool xaux_ext_Done(xaux_class_t *xc, aux_ext_data_t *aux_ext_data, Atom atom)
{
	AuxModule aux_module = NULL;
	char *class_name = NULL;

	DEBUG_printf("ext_Done im:0x%x, ic_id:0x%x\n", aux_ext_data->im, aux_ext_data->ic);
	DEBUG_printf("ext_Done: integer_count: %d, strings_count: %d\n", aux_ext_data->integer_count, aux_ext_data->string_count);

	class_name = XGetAtomName(gDisplay, atom);
	if (class_name == NULL)
		return False;

	DEBUG_printf("class_name: %s\n", class_name);
	aux_module = (AuxModule)aux_manager_get_module_by_classname(class_name);
	DEBUG_printf("aux_module: %p\n", aux_module);
	if (aux_module == NULL || aux_module->methods == NULL)
		return False;

	aux_module->methods->aux_module_Done(aux_ext_data);

	return True;
}

NotifyIntegerListDataToLanguageEngine(Display *display, 
int nIntegerCount, int *pIntegerList)
{
	aux_ext_data_t aux_ext_data;

	DEBUG_printf("im_:%d, ic_:%d\n", im_, ic_);

/*
	if (!im_ || !ic_ || !xc_)
		return;
*/

	aux_ext_data.im = im_;
	aux_ext_data.ic = ic_;
	aux_ext_data.integer_count = nIntegerCount;
	aux_ext_data.integer_list = pIntegerList;
	aux_ext_data.string_count = 0;
	aux_ext_data.string_list = NULL;
	aux_ext_data.string_ptr = NULL;
	aux_ext_data.point.x = 0;
	aux_ext_data.point.y = 0;

	DEBUG_printf("begin xaux_exe_setValue =============\n");
	xaux_ext_SetValue(display, xc_, &aux_ext_data);
	XFlush(display);
}

NotifyStringListDataToLanguageEngine(Display *display, 
int nIntegerCount, int *pIntegerList,
int nStringCount,  int *pStringLen,
char **pStringList)
{
	int i;

	aux_ext_data_t aux_ext_data;
	aux_ext_string_t *p;

	DEBUG_printf("im_:%d, ic_:%d\n", im_, ic_);

/*
	if (!im_ || !ic_ || !xc_)
		return;
*/

	aux_ext_data.im = im_;
	aux_ext_data.ic = ic_;
	aux_ext_data.integer_count = nIntegerCount;
	aux_ext_data.integer_list = pIntegerList;
	aux_ext_data.point.x = 0;
	aux_ext_data.point.y = 0;

	aux_ext_data.string_count = nStringCount;
	aux_ext_data.string_ptr = NULL;

	if (nStringCount > 0) {
		aux_ext_data.string_list = (aux_ext_string_t *) calloc(nStringCount, sizeof(aux_ext_string_t));
		for (i = 0; i < nStringCount; i++) {
			aux_ext_string_t *p = &aux_ext_data.string_list[i];
			p->length = pStringLen[i];
			p->ptr = (unsigned char *) (pStringList[i]);
		}
	}

	xaux_ext_SetValue(display, xc_, &aux_ext_data);
	XFlush(display);

	free(aux_ext_data.string_list);
}
