#include "Commands_InventoryRef.h"
#include "ParamInfos.h"

#if OBLIVION

#include "GameObjects.h"
#include "GameExtraData.h"
#include "GameAPI.h"
#include "GameForms.h"
#include "InventoryReference.h"

#if OBLIVION_VERSION == OBLIVION_VERSION_1_2_416
static const _Cmd_Execute Cmd_RemoveMe_Execute = (_Cmd_Execute)0x00500450;
#else
#error unsupported oblivion version
#endif

/*
static bool Cmd_RemoveMeIR_Execute(COMMAND_ARGS)
{
	*result = 0;
	if (thisObj) {
		InventoryReference* iref = InventoryReference::GetForRefID(thisObj->refID);
		if (iref) {
			TESObjectREFR* contRef = iref->GetContainer();
			BaseExtraList* dataList = NULL;

			TESObjectREFR* dest = NULL;
			if (ExtractArgs(PASS_EXTRACT_ARGS, &dest)) {
				Actor* contActor = OBLIVION_CAST(contRef, TESObjectREFR, Actor);
				if (contActor) {
					ExtraContainerChanges* xChanges = ExtraContainerChanges::GetForRef(contActor);
					if (xChanges) {
						// ###TODO: this looks like SetEquipped(TESForm*, bool) but returns an ExtraDataList, investigate
						dataList = (ExtraDataList*)ThisStdCall(0x00485FA0, xChanges, thisObj->baseForm, false);
					}
				}
			
				ExtraCount* xCount = (ExtraCount*)thisObj->baseExtraList.GetByType(kExtraData_Count);
				SInt16 count = xCount ? xCount->count : 1;
				contRef->RemoveItem(thisObj->baseForm, dataList, count, 0, 0, dest, 0, 0, 1, 0);

				// ###TODO: what does this do?
				ThisStdCall(0x00665260, *g_thePlayer, thisObj);
			}
			iref->SetRemoved();
		}
	}

	return true;
}
*/

static bool Cmd_RemoveMeIR_Execute(COMMAND_ARGS)
{
	*result = 0;
	if (thisObj) {
		InventoryReference* iref = InventoryReference::GetForRefID(thisObj->refID);
		if (iref) {
			TESObjectREFR* dest = NULL;
			if (ExtractArgs(PASS_EXTRACT_ARGS, &dest)) {
				if (dest) {
					*result = iref->MoveToContainer(dest) ? 1.0 : 0.0;
				}
				else {
					*result = iref->RemoveFromContainer() ? 1.0 : 0.0;
				}
			}
		}
	}

	return true;
}

static bool Cmd_CopyIR_Execute(COMMAND_ARGS)
{
	*result = 0;
	if (thisObj) {
		InventoryReference* iref = InventoryReference::GetForRefID(thisObj->refID);
		if (iref) {
			TESObjectREFR* dest = NULL;
			if (ExtractArgs(PASS_EXTRACT_ARGS, &dest) && dest) {
				*result = iref->CopyToContainer(dest) ? 1.0 : 0.0;
			}
		}
	}

	return true;
}

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

	TESForm* form = NULL;
	if (ExtractArgs(PASS_EXTRACT_ARGS, &form) && form) {
		InventoryReference* iref = InventoryReference::Create(NULL, InventoryReference::Data(form, NULL, NULL), false);
		if (iref) {
			*refResult = iref->GetRef()->refID;
		}
	}

	return true;
}

#endif

static ParamInfo kParams_OneOptionalContainerRef[1] =
{
	{ "containerRef",	kParamType_Container,	1	},
};

static ParamInfo kParams_OneContainerRef[1] =
{
	{	"containerRef",	kParamType_Container,	1	},
};

DEFINE_COMMAND(RemoveMeIR, "removes an inventory reference from its container, optionally transferring it to a different container, in much the same way as the vanilla RemoveMe command. The inventory reference becomes invalid once this command is called and should no longer be used.",
			   1, 1, kParams_OneOptionalContainerRef);
DEFINE_COMMAND(CopyIR, "copies an inventory reference to the specified container. The calling object needn't be in a container and remains valid after the command is called. If the calling object is equipped, the copy will not be equipped.",
			   1, 1, kParams_OneContainerRef);
DEFINE_COMMAND(CreateTempRef, "creates a temporary reference to the specified form. This reference does not exist in the gameworld or in a container, and remains valid for only one frame. It is mostly useful for creating a stack of one or more items to be added to a container with CopyIR",
			   0, 1, kParams_OneInventoryObject);
