#include "stdafx.h"
#include "ActorManager.h"

#include "ResourceManager.h"
#include "KFMTool.h"

cActorManager* cActorManager::Create( const char* kfmPathName, bool cumulativeAnimations )
{
	assert(kfmPathName);

	// Create KFM tool and load KFM file.
	cKFMToolPtr kfmTool = NiNew cKFMTool;
	if( kfmTool->LoadFile(kfmPathName) != NiKFMTool::KFM_SUCCESS )
	{
		assert( 0 );
		return NULL;
	}

	return Create( kfmTool, kfmPathName, cumulativeAnimations );
}

cActorManager* cActorManager::Create( NiKFMTool* kfmTool, const char* kfmPathName, bool cumulativeAnimations )
{
	assert(kfmTool && kfmPathName);

	// Build the KFM path.
	NiFilename kFilename(kfmPathName);
	char acKFMPath[NI_MAX_PATH];
	NiSprintf(acKFMPath, NI_MAX_PATH, "%s%s", kFilename.GetDrive(), 
		kFilename.GetDir());
	kfmTool->SetBaseKFMPath(acKFMPath);

	// Create actor manager.
	cActorManager* actorManager = NiNew cActorManager( kfmTool, cumulativeAnimations );

	// Initialize actor manager.
	if( actorManager->Initialize() == false )
	{
		NiDelete actorManager;
		return NULL;
	}

	return actorManager;
}

cActorManager::cActorManager( NiKFMTool* kfmTool, bool cumulativeAnimations )
: NiActorManager( kfmTool, cumulativeAnimations )
{
}

cActorManager::~cActorManager()
{
}

bool cActorManager::Initialize()
{
	if( LoadNIFFile() == false )
	{
		return false;
	}

	LoadSequences();
	return true;
}

bool cActorManager::LoadNIFFile()
{
	// Get model path.
	const char* modelPath = m_spKFMTool->GetModelPath();
	if (!modelPath)
	{
		return false;
	}

	const char* pathName = m_spKFMTool->GetFullModelPath();
	assert(pathName);

	NiAVObject* nifRoot = 0;
	if( RESOURCEMAN->LoadNIF( pathName, &nifRoot ) == false )
	{
		return false;
	}
	if( nifRoot == 0 )
	{
		return false;
	}
	return ChangeNIFRoot( nifRoot );
}

void cActorManager::LoadSequences()
{
	NiStream stream;

	// Iterate through entire array of sequence IDs.
	SequenceID* pSequenceIDs;
	unsigned int uiNumIDs;
	m_spKFMTool->GetSequenceIDs(pSequenceIDs, uiNumIDs);
	char acLastKFFilename[NI_MAX_PATH];
	acLastKFFilename[0] = '\0';
	for (unsigned int ui = 0; ui < uiNumIDs; ui++)
	{
		SequenceID eSequenceID = pSequenceIDs[ui];

		// Get KF filename.
		NiFixedString kKFFilename = m_spKFMTool->GetFullKFFilename(
			eSequenceID);
		assert(kKFFilename.Exists());

		// Determine whether or not to load file.
		bool bLoadKFFile = false;
		if (strcmp(acLastKFFilename, kKFFilename) != 0)
		{
			bLoadKFFile = true;
			NiStrcpy(acLastKFFilename, NI_MAX_PATH, kKFFilename);
		}

		AddSequence(eSequenceID, stream, bLoadKFFile);
	}
	NiFree(pSequenceIDs);
}

bool cActorManager::AddSequence( SequenceID sequenceID, NiStream& stream, bool loadKFFile )
{
	if (!m_spManager)
	{
		return false;
	}

	// Get sequence information.
	NiKFMTool::Sequence* pkKFMSequence = m_spKFMTool->GetSequence(
		sequenceID);
	if (!pkKFMSequence)
	{
		return false;
	}

	// Get KF filename.
	NiFixedString kKFFilename = m_spKFMTool->GetFullKFFilename(sequenceID);
	assert(kKFFilename.Exists());

	// Load file, if specified.
	if (loadKFFile)
	{
		cFileLoader loader;
		if( loader.Open( (const char*)kKFFilename, true ) == false )
		{
			return false;
		}

		bool bSuccess = stream.Load(kKFFilename);
		if (!bSuccess)
		{
			NILOG("cActorManager: Failed to load "
				"KF File: %s\n", (const char*) kKFFilename);
			return false;
		}
	}

	int iAnimIndex = pkKFMSequence->GetAnimIndex();
	NiControllerSequencePtr spSequence =
		NiControllerSequence::CreateSequenceFromFile(stream, iAnimIndex);
	if (!spSequence)
	{
		NILOG("cActorManager: Failed to add "
			"sequence at index %d in %s\n", iAnimIndex, 
			(const char*) kKFFilename);
		return false;
	}

	return ChangeSequence(sequenceID, spSequence);
}
