#pragma once

#include "GameTypes.h"
#include "NiNodes.h"

class TESObjectREFR;
class TESModel;

// Members of BSTask-derived objects are filled in as the task progresses through TaskManager/IOManager

// 4?
class BSTask
{
public:
	virtual void Unk_00(void) = 0;
	// more virtual funcs

	// void		** vtbl
	// TODO: no members?
};

// 18
class IOTask : public BSTask
{
public:
	virtual void Unk_00(void) = 0;

	IOTask();
	~IOTask();

	// void** vtbl
	BSTask	* unk04;		// 004 
	UInt32  unk08;			// 008 looks like a counter
	UInt32	unk0C;			// 00C 
	UInt32	unk10;			// 010 
	UInt32	unk14;			// 014 
};

// 38
class QueuedReference : public IOTask 
{
public:
	QueuedReference();
	~QueuedReference();

	UInt32			unk18;			// 018 
	BSTask			* unk1C;		// 01C seen QueuedChildren*
	TESObjectREFR	* refr;			// 020 
	UInt32			unk24;			// 024 
	UInt32			unk28;			// 028 
	UInt32			unk2C;			// 02C 
	UInt32			unk30;			// 030 
};

// 38
class QueuedModel : public IOTask
{
public:
	QueuedModel();
	~QueuedModel();

	struct NiNodeInfo
	{
		char		* nifPath;
		UInt32		unk04;
		NiNode		* niNode;
	};

	QueuedReference	* queuedRef;		// 018
	UInt32			unk01C;				// 01C
	char			* modelPath;		// 020
	void			* unk024;			// looks like pointer to raw data
	NiNodeInfo		* niNodeInfo;		// 028
	TESModel		* model;			// 02C
	UInt32			unk30;				// 030
	UInt8			flags;				// 034
	UInt8			pad35[3];
};

// 30
class BSTaskManager : public LockFreeMap< NiPointer< BSTask > >
{
public:
	virtual void Unk_0F(UInt32 arg0) = 0;
	virtual void Unk_10(UInt32 arg0) = 0;
	virtual void Unk_11(UInt32 arg0) = 0;
	virtual void Unk_12(void) = 0;
	virtual void Unk_13(UInt32 arg0) = 0;

	UInt32 unk1C;		// 1C
	UInt32 unk20;		// 20
	UInt32 unk24;		// 24
	UInt32 unk28;		// 28
	UInt32 unk2C;		// 2C
};

// 3C
class IOManager : public BSTaskManager
{
public:
	virtual void Unk_14(UInt32 arg0) = 0;

	static IOManager* GetSingleton();

	UInt32									unk30;			// 30
	LockFreeQueue< NiPointer< IOTask > >	* taskQueue;	// 34
	UInt32									unk38;			// 38

	bool IsInQueue(TESObjectREFR *refr);
	void QueueForDeletion(TESObjectREFR* refr);
	void DumpQueuedTasks();
};

extern IOManager** g_ioManager;
