#include "Commands_Cell.h"
#include "ParamInfos.h"
#include "Script.h"


#if OBLIVION

#include "GameObjects.h"
#include "GameExtraData.h"
#include "GameAPI.h"
#include "GameForms.h"
#include "ArrayVar.h"
#include "ScriptUtils.h"
#include "GameData.h"

static bool Cmd_GetCellMusicType_Execute(COMMAND_ARGS)
{
	*result = 0;
	TESObjectCELL* curCell = (*g_thePlayer)->parentCell;

	BSExtraData* xData = curCell->extraData.GetByType(kExtraData_CellMusicType);
	if (xData)
	{
		ExtraCellMusicType* xMusic = (ExtraCellMusicType*)Oblivion_DynamicCast(xData, 0, RTTI_BSExtraData, RTTI_ExtraCellMusicType, 0);
		if (xMusic)
			*result = xMusic->musicType;
	}

	return true;
}

static bool Cmd_SetCellWaterHeight_Execute(COMMAND_ARGS)
{
	*result = 0;
	TESObjectCELL* cell = NULL;
	float newHeight = 0;

	if (ExtractArgs(PASS_EXTRACT_ARGS, &cell, &newHeight) && cell)
		*result = cell->SetWaterHeight(newHeight) ? 1 : 0;

	return true;
}

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

	if(!thisObj) return true;
	TESObjectCELL* cell = thisObj->parentCell;
	if (!cell) return true;

	*result = cell->HasWater() ? 1 : 0;

	return true;
}

static bool Cmd_GetCellWaterHeight_Execute(COMMAND_ARGS)
{
	*result = 0;
	if(!thisObj) return true;
	TESObjectCELL* cell = thisObj->parentCell;
	if (!cell) return true;

	if (!cell->HasWater()) return true;

	float waterHeight = cell->GetWaterHeight();
	*result = waterHeight;
	return true;
}

static bool Cmd_GetCellDetachTime_Execute(COMMAND_ARGS)
{
	*result = -1;
	TESObjectCELL* cell = NULL;
	if (ExtractArgs(PASS_EXTRACT_ARGS, &cell) && cell)
	{
		ExtraDetachTime* detachTime = (ExtraDetachTime*)cell->extraData.GetByType(kExtraData_DetachTime);
		if (detachTime)
			*result = (SInt32)detachTime->detachTime;
	}
	return true;
}

static bool Cmd_GetCellResetHours_Execute(COMMAND_ARGS)
{
	*result = -1;
	TESObjectCELL* cell = NULL;
	if (ExtractArgs(PASS_EXTRACT_ARGS, &cell) && cell)
	{
		SInt32 iHoursToRespawn = TimeGlobals::HoursToRespawnCell();
		SInt32 iHoursPassed = TimeGlobals::GameHoursPassed();

		ExtraDetachTime* xDetach = (ExtraDetachTime*)cell->extraData.GetByType(kExtraData_DetachTime);
		if (xDetach)
		{
			SInt32 detachTime = xDetach->detachTime;
			if (xDetach->detachTime == 0xFFFFFFFF)		// ResetInterior sets it to this for immediate respawn
				*result = 0;
			else
			{
				detachTime += iHoursToRespawn;
				if (detachTime <= iHoursPassed)
					*result = 0;
				else
					*result = detachTime - iHoursPassed;
			}
		}
	}

	return true;
}

static bool Cmd_SetCellResetHours_Execute(COMMAND_ARGS)
{
	// specifies # of hours from now until cell reset
	*result = 0;
	TESObjectCELL* cell = NULL;
	UInt32 numHours = -1;
	if (ExtractArgs(PASS_EXTRACT_ARGS, &cell, &numHours) && cell && numHours != -1)
	{
		if (cell->IsInterior() && cell != (*g_thePlayer)->parentCell)
		{
			SInt32 iHoursToRespawn = TimeGlobals::HoursToRespawnCell();
			SInt32 iHoursPassed = TimeGlobals::GameHoursPassed();
			SInt32 detachTime = iHoursPassed + numHours - iHoursToRespawn;
			if (detachTime < iHoursPassed)
			{
				*result = 1;
				CALL_MEMBER_FN(cell, SetDetachTime)(detachTime);
				if (IsConsoleMode())
					Console_Print("Current hours passed :%d Detach time: %d", iHoursPassed, detachTime);
			}
			else if (IsConsoleMode())
				Console_Print("Detach time %d cannot be greater than current hours passed %d", detachTime, iHoursPassed);
		}
	}

	return true;
}

static bool Cmd_GetWorldSpaceParentWorldSpace_Execute(COMMAND_ARGS)
{
	TESWorldSpace* space = NULL;
	UInt32* refResult = (UInt32*)result;
	*refResult = 0;

	if (ExtractArgs(PASS_EXTRACT_ARGS, &space) && space && space->parentWorldspace)
		*refResult = space->parentWorldspace->refID;

	return true;
}

static bool Cmd_GetCellBehavesAsExterior_Execute(COMMAND_ARGS)
{
	TESObjectCELL* cell = NULL;
	*result = 0;

	if (ExtractArgs(PASS_EXTRACT_ARGS, &cell) && cell)
		if (cell->BehavesLikeExterior())
			*result = 1;

	if (IsConsoleMode())
		Console_Print("GetCellBehavesAsExterior >> %.0f", *result);

	return true;
}

#endif

CommandInfo kCommandInfo_GetCellMusicType =
{
	"GetCellMusicType", "GetMusicType", 0,
	"returns the music type associated with the player's current cell",
	0, 0, NULL,
	HANDLER(Cmd_GetCellMusicType_Execute),
	Cmd_Default_Parse,
	NULL,
	0
};

static ParamInfo kParams_SetWaterHeight[] =
{
	{	"cell",		kParamType_Cell,	0	},
	{	"height",	kParamType_Float,	0	},
};

DEFINE_COMMAND(SetCellWaterHeight, changes the height of water in a cell, 0, 2, kParams_SetWaterHeight);

CommandInfo kCommandInfo_ParentCellHasWater =
{
	"ParentCellHasWater",
	"HasWater",
	0,
	"returns whether the cell has water",
	1,
	0,
	NULL,
	HANDLER(Cmd_CellHasWater_Execute),
	Cmd_Default_Parse,
	NULL,
	0
};

CommandInfo kCommandInfo_GetParentCellWaterHeight =
{
	"GetParentCellWaterHeight",
	"GetWaterHeight",
	0,
	"returns the height of the cell's water",
	1,
	0,
	NULL,
	HANDLER(Cmd_GetCellWaterHeight_Execute),
	Cmd_Default_Parse,
	NULL,
	0
};

static ParamInfo kParams_OneCell[1] =
{
	{	"cell",	kParamType_Cell,	0	},
};

static ParamInfo kParams_OneCellOneInt[2] =
{
	{	"cell",	kParamType_Cell,	0	},
	{	"int",	kParamType_Integer,	0	},
};

DEFINE_COMMAND(GetCellDetachTime, returns the cell detach time, 0, 1, kParams_OneCell);
DEFINE_COMMAND(GetCellResetHours, returns the number of hours until a cell resets, 0, 1, kParams_OneCell);
DEFINE_COMMAND(SetCellResetHours, sets the number of hours until a cell resets, 0, 2, kParams_OneCellOneInt);

DEFINE_CMD_ALT(GetWorldSpaceParentWorldSpace, GetWorldParentWorld, returns a worldspaces parent worldspace, 0, kParams_OneWorldSpace);
DEFINE_COMMAND(GetCellBehavesAsExterior, returns 1 if the cell is flagged as behaving as an exterior, 0, 1, kParams_OneCell);
