#pragma once

#include <vector>
#include <string>

class IDataStream;

class Archive
{
public:
	Archive();
	~Archive();

	bool Read(IDataStream * src);
	void Extract(const char * dstRoot);

	void UseATIFourCC() { m_useATIFourCC = true; }

private:
	// 18
	struct Header
	{
		char	sig[4];				// 00 BTDX
		UInt32	version;			// 04 00000001
		char	type[4];			// 08 GNRL or DX10
		UInt32	numFiles;			// 0C
		UInt64	nameTableOffset;	// 10 - relative to start of file

		bool IsGeneral()
		{
			return memcmp(type, "GNRL", sizeof(type)) == 0;
		}

		bool IsDX10()
		{
			return memcmp(type, "DX10", sizeof(type)) == 0;
		}
	};

#pragma pack(push, 4)
	// 24
	struct FileEntry
	{
		UInt32	unk00;			// 00 - name hash?
		char	ext[4];			// 04 - extension
		UInt32	unk08;			// 08 - directory hash?
		UInt32	unk0C;			// 0C - flags? 00100100
		UInt64	offset;			// 10 - relative to start of file
		UInt32	packedLen;		// 18 - packed length (zlib)
		UInt32	unpackedLen;	// 1C - unpacked length
		UInt32	unk20;			// 20 - BAADF00D
	};
#pragma pack(pop)

	// 18
	struct FileEntry_DX10
	{
		UInt32	nameHash;		// 00
		char	ext[4];			// 04
		UInt32	dirHash;		// 08
		UInt8	unk0C;			// 0C
		UInt8	numChunks;		// 0D
		UInt16	chunkHdrLen;	// 0E - size of one chunk header
		UInt16	height;			// 10
		UInt16	width;			// 12
		UInt8	numMips;		// 14
		UInt8	format;			// 15 - DXGI_FORMAT
		UInt16	unk16;			// 16 - 0800
	};

	// 18
	struct DX10Chunk
	{
		UInt64	offset;			// 00
		UInt32	packedLen;		// 08
		UInt32	unpackedLen;	// 0C
		UInt16	startMip;		// 10
		UInt16	endMip;			// 12
		UInt32	unk14;			// 14 - BAADFOOD
	};

	struct Texture
	{
		FileEntry_DX10			hdr;
		std::vector <DX10Chunk>	chunks;
	};

	bool	m_useATIFourCC;
	Header	m_hdr;

	std::vector <FileEntry> m_files;
	std::vector <Texture> m_textures;

	std::vector <std::string> m_names;

	STATIC_ASSERT(sizeof(Header) == 0x18);
	STATIC_ASSERT(sizeof(FileEntry) == 0x24);

	IDataStream	* m_src;

	bool Read_General();
	bool Read_DX10();
	bool Read_Nametable();

	void Extract_General(const char * dstRoot);
	void Extract_DX10(const char * dstRoot);
};
