#include "XCircuit.h"
#include "utils.h"

static void menuitem_activated(Widget w, XCMenuItem *item, void *calldata)
{
	DISPPARAMS dispParams = { NULL, NULL, 0, 0 };
	VARIANT arg;

	if (item->target != NULL) {
		arg.vt = VT_UNKNOWN;
		arg.punkVal = &item->com.unk_iface;
		dispParams.rgvarg = &arg;
		dispParams.cArgs = 1;
		IDispatch_Invoke(item->target, 0, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispParams, NULL, NULL, NULL);
	}
}

static void menuitem_fire_event(Widget w, XCMenuItem *item, void *calldata)
{
	printf("Fire event from menu: %s\n", WinName(w));
	xccom_object_fire_event(&item->com, &DIID_DXCMenuEvents, 0x00001000);
}

STDMETHODIMP XCMenuItem_put_activated(IXCMenuItem *This, IDispatch *pDisp)
{
	XCMenuItem *item = (XCMenuItem*)TOCOMOBJ(This);

	if (item->target == NULL) {
		WinAddCallback((Widget)item->item, XtNselect, menuitem_activated, item);
		IUnknown_AddRef(This);
	} else
		IUnknown_Release(item->target);
	item->target = pDisp;
	IUnknown_AddRef(item->target);
	return S_OK;
}

STDMETHODIMP XCMenuItem_get_name(IXCMenuItem *This, BSTR *pVal)
{
	XCMenuItem *item = (XCMenuItem*)TOCOMOBJ(This);
	if (*pVal != NULL) {
		SysFreeString(*pVal);
		*pVal = NULL;
	}
	*pVal = convert_to_bstr((char*)WinName((Widget)item->item));
	return S_OK;
}

STDMETHODIMP XCMenuItem_reset(IXCMenuItem *This)
{
	XCMenuItem *item = (XCMenuItem*)TOCOMOBJ(This);

	if (!WinIsPopupMenu((Widget)item->item)) {
		WinRemoveCallback((Widget)item->item, XtNselect, menuitem_fire_event, item);
		IUnknown_Release(This);
	}
	if (item->target != NULL) {
		WinRemoveCallback((Widget)item->item, XtNselect, menuitem_activated, item);
		IUnknown_Release(item->target);
		item->target = NULL;
		IUnknown_Release(This);
	}
	WinRemoveAllCallbacks(item->item, XtNselect);
	if (!WinIsPopupMenu((Widget)item->item)) {
		WinAddCallback((Widget)item->item, XtNselect, menuitem_fire_event, item);
		IUnknown_AddRef(This);
	}
	return S_OK;
}

static IXCMenuItemVtbl vtbl = {
	/* IUnknown */
	NULL,
	NULL,
	NULL,
	/* IXCMenuItem */
	XCMenuItem_put_activated,
	XCMenuItem_get_name,
	XCMenuItem_reset,
};

XCMenuItem* make_XCMenuItem(void *item)
{
	XtCallbackProc proc = (XtCallbackProc)menuitem_activated;
	XCMenuItem *ptr = NULL;

	if (WinFindCallback((Widget)item, XtNselect, &proc, (void**)&ptr) != 0 ||
	    ((proc = (XtCallbackProc)menuitem_fire_event) &&
	     WinFindCallback((Widget)item, XtNselect, &proc, (void**)&ptr) != 0)) {
		return ptr;
	}
	
	ptr = (XCMenuItem*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, sizeof(XCMenuItem));
	xccom_object_init(&ptr->com);
	xccom_object_add_interface(&ptr->com, &IID_IXCMenuItem, &vtbl);
	xccom_object_create_dispatch_interface(&ptr->com, &IID_IXCMenuItem, COM_get_typeinfo(&IID_IXCMenuItem));
	xccom_object_add_connectionpoint(&ptr->com, &DIID_DXCMenuEvents);
	ptr->item = item;
	if (!WinIsPopupMenu((Widget)item)) {
		WinAddCallback((Widget)item, XtNselect, menuitem_fire_event, ptr);
		IUnknown_AddRef(&ptr->com.unk_iface);
	}
	return ptr;
}
