#include "GameObjects.h"
#include "GameTiles.h"
#include "GameMenus.h"
#include "Commands_Menu.h"
#include "GameAPI.h"
#include "GameForms.h"
#include "ParamInfos.h"


#if OBLIVION

#include "StringVar.h"

typedef void (* _CloseAllMenus)(void);
#if OBLIVION_VERSION == OBLIVION_VERSION_1_1

static _CloseAllMenus CloseAllMenus = (_CloseAllMenus)0x0056C910;

#elif OBLIVION_VERSION == OBLIVION_VERSION_1_2

static _CloseAllMenus CloseAllMenus = (_CloseAllMenus)0x00579670;

#elif OBLIVION_VERSION == OBLIVION_VERSION_1_2_416

static _CloseAllMenus CloseAllMenus = (_CloseAllMenus)0x00579770;

#else

#error unsupported oblivion version

#endif

static bool Cmd_GetActiveMenuMode_Execute(COMMAND_ARGS)
{
	*result = 0;
	InterfaceManager* intfc = InterfaceManager::GetSingleton();
	if (intfc && intfc->activeMenu)
		*result = intfc->activeMenu->id;

	return true;
}

static enum eMenuValue {
	//no params
	kMenu_Soulgem,
	kMenu_EnchantItem,
	kMenu_Barter,
	kMenu_ContainerView,

	//one optional int param
	kMenu_Selection,
	kMenu_Object,
	kMenu_Ref,
	kMenu_Filter,

	//one int param
	kMenu_Ingredient,
	kMenu_IngredientCount,
	kMenu_Apparatus
};

union MenuInfo {
	const TESForm* form;
	UInt32	 integer;
};

static bool GetActiveMenuElement(COMMAND_ARGS, eMenuValue whichValue, MenuInfo* out, UInt32 whichMenu = 0)
{
	InterfaceManager* intfc = InterfaceManager::GetSingleton();
	Menu* activeMenu = intfc->activeMenu;
	Tile* activeTile = intfc->activeTile;
	bool gotValue = false;
	UInt32 intArg = -1;

	//Extract arguments
	if (whichValue < kMenu_Ingredient && whichValue >= kMenu_Selection)	//optional int param specifies menu type
	{
		ExtractArgs(EXTRACT_ARGS, &intArg);
		if (intArg != -1)
			activeMenu = GetMenuByType(intArg);
	}
	else if (whichValue >= kMenu_Ingredient)
	{
		ExtractArgs(EXTRACT_ARGS, &intArg);
		if (intArg == -1)
			return false;
	}

	if (whichMenu)	//specific menu, so look it up directly
		activeMenu = GetMenuByType(whichMenu);

	if (!activeMenu)
		return false;

	//get element based on menu type
	switch (activeMenu->id)
	{
	case kMenuType_Message:
		{
			MessageMenu* msgMenu = (MessageMenu*)activeMenu;
			switch (whichValue)
			{
			case kMenu_Object:
				if (ShowMessageBox_pScriptRefID && msgMenu->IsScriptMessageBox())
				{
					out->form = LookupFormByID(*ShowMessageBox_pScriptRefID);
					gotValue = true;
				}
				else
					out->form = 0;
			default:
				break;
			}
		}
		break;
	case kMenuType_Alchemy:
		{
			AlchemyMenu* menu = (AlchemyMenu*)activeMenu;
			switch (whichValue)
			{
			case kMenu_Object:
				out->form = menu->potion;
				gotValue = true;
				break;
			case kMenu_Ingredient:
				out->form = menu->GetIngredientItem(intArg);
				gotValue = true;
				break;
			case kMenu_IngredientCount:
				out->integer = menu->GetIngredientCount(intArg);
				gotValue = true;
				break;
			case kMenu_Apparatus:
				out->form = menu->GetApparatus(intArg);
				gotValue = true;
				break;
			default:
				break;
			}
		}
		break;
	case kMenuType_Container:
		{
			ContainerMenu* menu = (ContainerMenu*)activeMenu;
			switch (whichValue)
			{
			case kMenu_ContainerView:
				if (menu->isContainerContents)
					out->integer = 0;
				else
					out->integer = 1;
				gotValue = true;
				break;
			case kMenu_Ref:
				{
					out->form = menu->refr;
					gotValue = true;
					break;
				}
			case kMenu_Filter:
				out->integer = menu->filterType;
				gotValue = true;
				break;
			case kMenu_Selection:
				{
					if (activeTile)
					{
						float fIndex;
						if (activeTile->GetFloatValue(kTileValue_user11, &fIndex))
						{
							UInt32 index = fIndex;
							if (menu->isContainerContents)
								out->form = menu->refr->GetInventoryItem(index, menu->isBarter);
							else
								out->form = (*g_thePlayer)->GetInventoryItem(index, 0);
							gotValue = true;
						}
					}
				}
				break;
			case kMenu_Barter:
				out->integer = menu->isBarter;
				gotValue = true;
				break;
			default:
				break;
			}
			break;
		}
	case kMenuType_Magic:
		{
			MagicMenu* menu = (MagicMenu*)activeMenu;
			switch (whichValue)
			{
			case kMenu_Selection:
				{
					if (activeTile && menu->filterType != MagicMenu::kFilter_ActiveEffects)
					{
						float fIndex;
						if (activeTile->GetFloatValue(kTileValue_user11, &fIndex))
						{
							UInt32 index = fIndex;
							out->form = MenuSpellListVisitor(&menu->spells).GetNthInfo(index);
							gotValue = true;
						}
					}
				}
				break;
			case kMenu_Filter:
				out->integer = menu->filterType;
				gotValue = true;
				break;
			default:
				break;
			}
			break;
		}
	case kMenuType_SpellPurchase:
		{
			SpellPurchaseMenu* menu = (SpellPurchaseMenu*)activeMenu;
			switch (whichValue)
			{
			case kMenu_Selection:
				{
					if (activeTile)
					{
						float fIndex;
						if (activeTile->GetFloatValue(kTileValue_user11, &fIndex))
						{
							UInt32 index = fIndex;
							out->form = MenuSpellListVisitor(&menu->spells).GetNthInfo(index);
							gotValue = true;
						}
					}
					break;
				}
			case kMenu_Ref:
				{
					out->form = menu->spellMerchant;
					gotValue = true;
					break;
				}
			default:
				break;
			}
		}
		break;
	case kMenuType_Enchantment:
		{
			EnchantmentMenu* menu = (EnchantmentMenu*)activeMenu;
			switch (whichValue)
			{
			case kMenu_Soulgem:
				if (menu->soulGemInfo)
				{
					out->form = menu->soulGemInfo->form;
					gotValue = true;
				}
				break;
			case kMenu_EnchantItem:
				out->form = menu->enchantItem;
				gotValue = true;
				break;
			default:
				break;
			}
		}
		break;
	case kMenuType_Book:
		{
			BookMenu* menu = (BookMenu*)activeMenu;
			switch (whichValue)
			{
			case kMenu_Ref:
				out->form = menu->bookRef;
				gotValue = true;
				break;
			case kMenu_Object:
				out->form = menu->book;
				gotValue = true;
				break;
			default:
				break;
			}
		}
		break;
	case kMenuType_Inventory:
		{
			InventoryMenu* menu = (InventoryMenu*)activeMenu;
			switch (whichValue)
			{
			case kMenu_Selection:
				{
					if (activeTile)
					{
						float fIndex;
						if (activeTile->GetFloatValue(kTileValue_user11, &fIndex))
						{
							UInt32 index = fIndex;
							out->form = (*g_thePlayer)->GetInventoryItem(index, 0);
							gotValue = true;
						}
					}
				}
				break;
			case kMenu_Filter:
				out->integer = menu->filterType;
				gotValue = true;
				break;
			default:
				break;
			}
		}
		break;
	case kMenuType_Dialog:
		{
			DialogMenu* menu = (DialogMenu*)activeMenu;
			switch (whichValue)
			{
			case kMenu_Ref:
				out->form = menu->speaker;
				gotValue = true;
				break;
			default:
				break;
			}
		}
		break;
	default:
		break;
	}

	return gotValue;
}

static bool Cmd_GetEnchMenuEnchItem_Execute(COMMAND_ARGS)
{
	UInt32* refResult = (UInt32*)result;
	*refResult = 0;

	MenuInfo info;
	if (GetActiveMenuElement(PASS_COMMAND_ARGS, kMenu_EnchantItem, &info, kMenuType_Enchantment) && info.form)
		*refResult = info.form->refID;

	return true;
}

static bool Cmd_GetEnchMenuSoulgem_Execute(COMMAND_ARGS)
{
	UInt32* refResult = (UInt32*)result;
	*refResult = 0;

	MenuInfo info;
	if (GetActiveMenuElement(PASS_COMMAND_ARGS, kMenu_Soulgem, &info, kMenuType_Enchantment) && info.form)
		*refResult = info.form->refID;

	return true;
}

static bool Cmd_GetActiveMenuSelection_Execute(COMMAND_ARGS)
{
	UInt32* refResult = (UInt32*)result;
	*refResult = 0;

	MenuInfo info;
	if (GetActiveMenuElement(PASS_COMMAND_ARGS, kMenu_Selection, &info) && info.form)
	{
		*refResult = info.form->refID;
		if (IsConsoleMode())
			Console_Print("GetActiveMenuSelection >> %s (%08x)", GetFullName(const_cast<TESForm*>(info.form)), info.form->refID);
	}

	return true;
}

static bool Cmd_GetActiveMenuObject_Execute(COMMAND_ARGS)
{
	UInt32* refResult = (UInt32*)result;
	*refResult = 0;

	MenuInfo info;
	if (GetActiveMenuElement(PASS_COMMAND_ARGS, kMenu_Object, &info) && info.form)
		*refResult = info.form->refID;

	return true;
}

static bool Cmd_GetActiveMenuRef_Execute(COMMAND_ARGS)
{
	UInt32* refResult = (UInt32*)result;
	*refResult = 0;

	MenuInfo info;
	if (GetActiveMenuElement(PASS_COMMAND_ARGS, kMenu_Ref, &info) && info.form)
		*refResult = info.form->refID;

	return true;
}

static bool Cmd_GetActiveMenuFilter_Execute(COMMAND_ARGS)
{
	*result = 0;

	MenuInfo info;
	if (GetActiveMenuElement(PASS_COMMAND_ARGS, kMenu_Filter, &info))
		*result = info.integer;

	return true;
}

static bool Cmd_IsBarterMenuActive_Execute(COMMAND_ARGS)
{
	*result = 0;

	MenuInfo info;
	if (GetActiveMenuElement(PASS_COMMAND_ARGS, kMenu_Barter, &info))
		*result = (info.integer) ? 1 : 0;

	return true;
}

static bool Cmd_GetAlchMenuIngredient_Execute(COMMAND_ARGS)
{
	UInt32* refResult = (UInt32*)result;
	*refResult = 0;

	MenuInfo info;
	if (GetActiveMenuElement(PASS_COMMAND_ARGS, kMenu_Ingredient, &info, kMenuType_Alchemy) && info.form)
		*refResult = info.form->refID;
	
	return true;
}

static bool Cmd_GetAlchMenuIngredientCount_Execute(COMMAND_ARGS)
{
	*result = -1;

	MenuInfo info;
	if (GetActiveMenuElement(PASS_COMMAND_ARGS, kMenu_IngredientCount, &info, kMenuType_Alchemy))
		*result = info.integer;

	return true;
}

static bool Cmd_GetAlchMenuApparatus_Execute(COMMAND_ARGS)
{
	UInt32* refResult = (UInt32*)result;
	*refResult = 0;

	MenuInfo info;
	if (GetActiveMenuElement(PASS_COMMAND_ARGS, kMenu_Apparatus, &info, kMenuType_Alchemy) && info.form)
		*refResult = info.form->refID;

	return true;
}

/*	Need to figure out what BaseExtraList* and unk4 do in ApparatusInfo struct first
static bool Cmd_SetAlchMenuApparatus_Execute(COMMAND_ARGS)
{
	UInt32 whichAppa = 0;
	TESForm* newAppa = NULL;
	*result = 0;

	if (ExtractArgs(PASS_EXTRACT_ARGS, &whichAppa, &newAppa))
	{
		Menu* menu = GetMenuByType(kMenuType_Alchemy);
		if (alchMenu)
		{
			AlchemyMenu* alchMenu = (AlchemyMenu*)menu;
			alchMenu->
*/

static bool Cmd_CloseAllMenus_Execute(COMMAND_ARGS)
{
	CloseAllMenus();
	return true;
}


static bool Cmd_GetContainerMenuView_Execute(COMMAND_ARGS)
{
	*result = -1;

	MenuInfo info;
	if (GetActiveMenuElement(PASS_COMMAND_ARGS, kMenu_ContainerView, &info, kMenuType_Container))
		*result = info.integer;

	return true;
}

static enum {
	kGetFloat,
	kSetFloat,
	kGetString,
	kSetString,
	kExists
};

static bool GetSetMenuValue_Execute(COMMAND_ARGS, UInt32 mode)
{
	const char* separatorChar = GetSeparatorChars();
	char stringArg[kMaxMessageLength] = { 0 };
	UInt32 menuType = 0;
	float newFloatVal = 0;
	char* newStringVal = NULL;
	
	char* componentPath = stringArg;

	bool bExtracted = false;
	switch (mode)
	{
	case kGetFloat:
	case kGetString:
	case kExists:
		bExtracted = ExtractFormatStringArgs(0, stringArg, paramInfo, arg1, opcodeOffsetPtr, scriptObj, eventList, kCommandInfo_GetMenuFloatValue.numParams, &menuType);
		break;
	case kSetFloat:
		bExtracted = ExtractFormatStringArgs(0, stringArg, paramInfo, arg1, opcodeOffsetPtr, scriptObj, eventList, kCommandInfo_SetMenuFloatValue.numParams, &menuType, &newFloatVal);
		break;
	case kSetString:
		{
			bExtracted = ExtractFormatStringArgs(0, stringArg, paramInfo, arg1, opcodeOffsetPtr, scriptObj, eventList, kCommandInfo_GetMenuFloatValue.numParams, &menuType);
			// extract new value from format string
			char* context = NULL;
			componentPath = strtok_s(stringArg, separatorChar, &context);
			newStringVal = strtok_s(NULL, separatorChar, &context);
			bExtracted = (bExtracted && componentPath && newStringVal);
		}
		break;
	}

	char* strToAssign = "";

	if (bExtracted)
	{
		Menu* menu = GetMenuByType(menuType);
		if (menu && menu->tile)
		{
			Tile::Value* val = menu->tile->GetValueByName(componentPath);
			if (val)
			{
				DEBUG_PRINT("Value Address: %08x", val);
#if _DEBUG
				val->DumpExpressionList();
#endif
				switch (mode)
				{
				case kExists:
					*result = 1;
					break;
				case kGetFloat:
					if (val->IsNum())
						*result = val->num;
					break;
				case kSetFloat:
					val->bIsNum = 1;
					val->parentTile->UpdateFloat(val->id, newFloatVal);
					val->num = newFloatVal;
					val->parentTile->UpdateField(val->id, newFloatVal, NULL);

					break;
				case kGetString:
					if (val->IsString())
						strToAssign = val->str.m_data;
					break;
				case kSetString:
					val->bIsNum = 0;
					val->parentTile->UpdateString(val->id, newStringVal);
					val->parentTile->SetStringValue(val->id, newStringVal);
					val->parentTile->UpdateField(val->id, 0, newStringVal);

					break;
				}
			}
		}
	}

	if (mode == kGetString)		// need to assign even if errors occur during arg extraction/value retrieval
		AssignToStringVar(PASS_COMMAND_ARGS, strToAssign);

	return true;
}

static bool Cmd_GetMenuFloatValue_Execute(COMMAND_ARGS)
{
	return GetSetMenuValue_Execute(PASS_COMMAND_ARGS, kGetFloat);
}

static bool Cmd_GetMenuStringValue_Execute(COMMAND_ARGS)
{
	return GetSetMenuValue_Execute(PASS_COMMAND_ARGS, kGetString);
}

static bool Cmd_SetMenuFloatValue_Execute(COMMAND_ARGS)
{
	return GetSetMenuValue_Execute(PASS_COMMAND_ARGS, kSetFloat);
}

static bool Cmd_SetMenuStringValue_Execute(COMMAND_ARGS)
{
	return GetSetMenuValue_Execute(PASS_COMMAND_ARGS, kSetString);
}

static bool Cmd_GetMenuHasTrait_Execute(COMMAND_ARGS)
{
	*result = 0;
	return GetSetMenuValue_Execute(PASS_COMMAND_ARGS, kExists);
}

static bool Cmd_SetButtonPressed_Execute(COMMAND_ARGS)
{
	UInt32 button = 0;
	if (ExtractArgs(PASS_EXTRACT_ARGS, &button))
	{
		MessageMenu* menu = (MessageMenu*)GetMenuByType(kMenuType_Message);
		if (menu)
			menu->HandleClick(menu->kButtonID_Button1 + button, 0);
	}

	return true;
}

static bool Cmd_GetActiveUIComponentName_Execute(COMMAND_ARGS)
{
	const char* name = "";

	InterfaceManager* intfc = InterfaceManager::GetSingleton();
	if (intfc->activeTile)
		name = intfc->activeTile->name.m_data;

	AssignToStringVar(PASS_COMMAND_ARGS, name);
	return true;
}

static bool Cmd_GetActiveUIComponentFullName_Execute(COMMAND_ARGS)
{
	const char* name = "";
	std::string nameStr;

	InterfaceManager* intfc = InterfaceManager::GetSingleton();
	if (intfc->activeTile)
	{
		nameStr = intfc->activeTile->GetQualifiedName();
		name = nameStr.c_str();
	}

	AssignToStringVar(PASS_COMMAND_ARGS, name);
	return true;
}

static bool Cmd_GetActiveUIComponentID_Execute(COMMAND_ARGS)
{
	*result = -1;

	InterfaceManager* intfc = InterfaceManager::GetSingleton();
	if (intfc->activeTile)
	{
		float id;
		if (intfc->activeTile->GetFloatValue(kTileValue_id, &id))
			*result = id;
	}

	return true;
}

static bool Cmd_ClickMenuButton_Execute(COMMAND_ARGS)
{
	UInt32 menuType;
	char name[kMaxMessageLength] = { 0 };

	if (ExtractFormatStringArgs(0, name, paramInfo, arg1, opcodeOffsetPtr, scriptObj, eventList, kCommandInfo_GetMenuFloatValue.numParams, &menuType))
	{
		Menu* menu = GetMenuByType(menuType);
		if (menu && name)
		{
			UInt32 buttonID = 0;
			Tile* parentTile = NULL;

			if (name[0] == '#')		// component specified by ID rather than name
			{
				buttonID = atoi(name + 1);
				parentTile = menu->tile->GetChildByIDTrait(buttonID);
			}
			else		// roundabout way of getting a button tile - look up the <id> trait then take the parent tile
			{
				UInt32 nameLen = strlen(name);
				name[nameLen] = '\\';
				name[nameLen+1] = 'i';
				name[nameLen+2] = 'd';
				name[nameLen+3] = '\0';

				Tile::Value* val = menu->tile->GetValueByName(name);
				if (val)
				{
					buttonID = val->num;
					parentTile = val->parentTile;
				}
			}

			DEBUG_PRINT("Parent Tile: %08x, ID: %d", parentTile, buttonID);
			if (parentTile)
				menu->HandleClick(buttonID, parentTile);
		}
	}

	return true;
}

#include "obse_common/SafeWrite.h"
#include "GameTasks.h"

#include "Hooks_Gameplay.h"
// testing code to hook ExtractArgs to allow string vars to substitute for literal strings

static __declspec(naked) void ExtractStringHook(void)
{
	// This hooks immediately before a call to memcpy().
	// Original code copies a string literal from script data to buffer
	// If string is of format _localVariableName, replace literal with contens of string var

	static char* dest;			// buffer to hold extracted string
	static char* scriptData;	// pointer to beginning of string in script data
	static UInt32 dataLen;		// length of string
	static ScriptEventList* eventList;

	static UInt32 kRetnAddress = 0x004FB1F4;

	__asm {
		// Grab the args to memcpy()
		mov dest, edi
		mov scriptData, eax
		mov dataLen, ebp

		// Grab the eventList
		mov eax, [esp + 0x50]
		mov eventList, eax

		pushad
	}

	memcpy(dest, scriptData, dataLen);
	dest[dataLen] = 0;
	
	if (dataLen && dest[0] == '_' && eventList && eventList->m_script)
	{
		Script::VariableInfo* varInfo = eventList->m_script->GetVariableByName(dest + 1);
		if (varInfo)
		{
			ScriptEventList::Var* var = eventList->GetVariable(varInfo->idx);
			if (var)
			{
				StringVar* strVar = g_StringMap.Get(var->data);
				if (strVar)
					if (strVar->GetLength() < 0x100)
						strcpy_s(dest, strVar->GetLength(), strVar->GetCString());
			}
		}
	}

	Console_Print("String: %s eventList: %08x", dest, eventList);

	__asm {
		popad
		jmp [kRetnAddress]
	}
}

static bool Cmd_Debug_Execute(COMMAND_ARGS)
{
	InterfaceManager::GetSingleton()->menuRoot->DebugDump();
	return true;

	WriteRelJump(0x004FB1EB, (UInt32)ExtractStringHook);
	return true;

	IOManager* ioMan = IOManager::GetSingleton();
	if (!ioMan)
		Console_Print("No IOMan!");
	else
		ioMan->DumpQueuedTasks();
	
	return true;

	static bool done = false;
	if (!done)
	{
		WriteRelJump(0x004FB201, (UInt32)&ExtractStringHook);
		done = true;
	}

	return true;

	InterfaceManager* intfc = InterfaceManager::GetSingleton();
	DumpClass(intfc, sizeof(InterfaceManager)/4);

	return true;

	if (thisObj)
	{
		TESObjectBOOK* book = (TESObjectBOOK*)Oblivion_DynamicCast(thisObj->baseForm, 0, RTTI_TESForm, RTTI_TESObjectBOOK, 0);
		if (book)
		{
			const char* desc = book->description.GetText(0, 0x43534544);
			if (desc)
				_MESSAGE("%s", desc);
			else
				DEBUG_PRINT("Couldn't read book text");
		}
	}

	return true;

	if (arg3)
	{
		TESObjectREFR* arg3Ref = (TESObjectREFR*)arg3;
		Console_Print("Arg3: %s %08x", GetFullName(arg3Ref), arg3Ref->refID);
	}

	return true;
}

#endif






DEFINE_COMMAND(GetActiveMenuMode,
			   returns the code for the menu over which the mouse is positioned,
			   0,
			   0,
			   NULL);

DEFINE_COMMAND(GetEnchMenuEnchItem,
			   returns the selected enchantment item,
			   0,
			   0,
			   NULL);

DEFINE_COMMAND(GetEnchMenuSoulgem,
			   returns the selected soulgem,
			   0,
			   0,
			   NULL);

DEFINE_COMMAND(GetActiveMenuObject,
			   returns the base object from which the active menu is derived,
			   0,
			   1,
			   kParams_OneOptionalInt);

DEFINE_COMMAND(GetActiveMenuRef,
			   returns the ref from which the active menu is derived,
			   0,
			   1,
			   kParams_OneOptionalInt);

DEFINE_COMMAND(GetActiveMenuSelection,
			   returns the selected item in the active menu,
			   0,
			   1,
			   kParams_OneOptionalInt);

DEFINE_COMMAND(GetActiveMenuFilter,
			   returns the filter code for the active menu,
			   0,
			   1,
			   kParams_OneOptionalInt);

DEFINE_COMMAND(IsBarterMenuActive,
			   returns 1 if the barter menu is active,
			   0,
			   0,
			   NULL);

DEFINE_COMMAND(GetAlchMenuIngredient,
			   returns the nth ingredient selected in the Alchemy interface,
			   0,
			   1,
			   kParams_OneInt);

DEFINE_COMMAND(GetAlchMenuIngredientCount,
			   returns the count of the nth ingredient selected in the Alchemy interface,
			   0,
			   1,
			   kParams_OneInt);

DEFINE_COMMAND(GetAlchMenuApparatus,
			   returns the nth apparatus selected in the alchemy interface,
			   0,
			   1,
			   kParams_OneInt);

DEFINE_COMMAND(GetContainerMenuView,
			   returns 1 if the player is looking at his own inventory,
			   0,
			   0,
			   NULL);

static ParamInfo kParams_SetAlchMenuApparatus[2] =
{
	{	"int",		 kParamType_Integer,		 0	},
	{	"apparatus", kParamType_InventoryObject, 0	},
};

/*
DEFINE_COMMAND(SetAlchMenuApparatus,
			   sets the apparatus being used for brewing potions,
			   0,
			   2,
			   kParams_SetAlchMenuApparatus);
*/

DEFINE_COMMAND(CloseAllMenus,
			   closes all open menus,
			   0,
			   0,
			   NULL);

static ParamInfo kParams_GetMenuValue[SIZEOF_FMT_STRING_PARAMS + 1] =
{
	FORMAT_STRING_PARAMS,
	{	"menuType",	kParamType_Integer,	0	},
};

DEFINE_COMMAND(GetMenuFloatValue,
			   returns a float value for the specified menu component,
			   0,
			   NUM_PARAMS(kParams_GetMenuValue),
			   kParams_GetMenuValue);

DEFINE_COMMAND(GetMenuStringValue,
			   returns a string value for the specified menu component,
			   0,
			   NUM_PARAMS(kParams_GetMenuValue),
			   kParams_GetMenuValue);

static ParamInfo kParams_SetMenuFloatValue[SIZEOF_FMT_STRING_PARAMS + 2] =
{
	FORMAT_STRING_PARAMS,
	{	"menuType",		kParamType_Integer,	0	},
	{	"new value",	kParamType_Float,	0	},
};

DEFINE_COMMAND(SetMenuFloatValue,
			   sets a float value for the specified menu component,
			   0,
			   NUM_PARAMS(kParams_SetMenuFloatValue),
			   kParams_SetMenuFloatValue);

DEFINE_COMMAND(SetMenuStringValue,
			   sets a string value for the specified menu component,
			   0,
			   NUM_PARAMS(kParams_GetMenuValue),
			   kParams_GetMenuValue);

DEFINE_COMMAND(GetMenuHasTrait,
			   returns 1 if the specified trait exists,
			   0,
			   NUM_PARAMS(kParams_GetMenuValue),
			   kParams_GetMenuValue);

DEFINE_COMMAND(SetButtonPressed,
			   forces a messagebox button press,
			   0,
			   1,
			   kParams_OneInt);

DEFINE_COMMAND(GetActiveUIComponentName,
			   returns the name of the highlighted UI component such as a button,
			   0,
			   0,
			   NULL);

DEFINE_COMMAND(GetActiveUIComponentFullName,
			   returns the qualified name of the highlighted UI component,
			   0,
			   0,
			   NULL);

DEFINE_COMMAND(GetActiveUIComponentID,
			   returns the ID of the highlighted UI component as defined in the menu XML,
			   0,
			   0,
			   NULL);

DEFINE_COMMAND(ClickMenuButton,
			   simulates a mouse click of the specified button,
			   0,
			   NUM_PARAMS(kParams_GetMenuValue),
			   kParams_GetMenuValue);

#ifdef _DEBUG
DEFINE_COMMAND(Debug,
			   nothing,
			   0,
			   0,
			   NULL);
#endif