////////////////////////////////////////////////////////////////////////////////
// MechWarrior4Reader.cpp
// MechWarrior 4 resource file parser - todo: does not work yet, incomplete, work in progress
// Copyright Bjoern Ganster
// Developed since 2023

#include "MechWarrior4Reader.h"

#define FILE_NUMBER FILE_NO_MW4_RESOURCE_FILE_READER_CPP

// Constructor
MW4ResourceFileReader::MW4ResourceFileReader()
: MWArchive("MW4ResourceFileReader", MW4ResourceFileReader_ID)
{
}

// Destructor
MW4ResourceFileReader::~MW4ResourceFileReader()
{
}

struct MW4FileRecord {
	BYTE magic[8];
	DWORD unpackedSize;
	DWORD packedSize;
	DWORD dataOffset;
	WORD fileNo;
	BYTE nameLen;
};

// Open file
bool MW4ResourceFileReader::open(const PathChar* PRJFN, bool)
{
	SET_SCOPE;
	bool result = mMb.loadFromFile(PRJFN);
	if (!result || mMb.getSize() < 256) {
		RETURN false;
	}

	// Check signature
	SET_OP;
	if (mMb.get<unsigned char>(0) != '#'
	||  mMb.get<unsigned char>(1) != 'V'
	||  mMb.get<unsigned char>(2) != 'B'
	||  mMb.get<unsigned char>(3) != 'D')
	{
		RETURN false;
	}

	// Analase TOC
	SET_OP;
	DWORD tocSize = mMb.get<DWORD>(0x0c);
	DWORD tocOffset = 0x14;
	//int fileNo = 0;
	while (tocOffset < tocSize) {
		MW4FileRecord* fileRecord = mMb.getPtr<MW4FileRecord>(tocOffset);
		BYTE nameLen = mMb.get<BYTE>(tocOffset+22);
		BGCPString name(mMb.getPtr<unsigned char>(tocOffset+23, false), nameLen, CP_ASCII);

		/*COUT << "File " << fileNo << ", toc offset: " << tocOffset 
			<< ", unpacked size: " << fileRecord->unpackedSize << ", packed size: "
			<< fileRecord->packedSize << ", data offset: " << dataOffset << ", file name: ";
		name.printLn();*/
		//mMb.dump(tocOffset, 23);

		ArchiveEntry entry;
		entry.fileSize = fileRecord->unpackedSize;
		entry.packedSize = fileRecord->packedSize;
		entry.fileOffset = fileRecord->dataOffset + tocSize;
		//entry.filename = name;
		//entry.fileType = ???;

		// MW2 resource files may contain paths, delimited by backslashes (and, even slashes)
		// Since we don't really support these paths, simply replace the backslashes with underscores,
		// at least for the time being, until maybe I find the time to implement something better ...
		name = name.replace("\\", "_");
		entry.filename = name.replace("/", "_");

		mEntries.push_back(entry);
		tocOffset += nameLen + 23;
		//++fileNo;
	}

	RETURN result;
}

// Close file
void MW4ResourceFileReader::close()
{
}

// Read bufSize bytes from file numbered index at offset into buf
bool MW4ResourceFileReader::getFileChunk(size_t index, size_t offset, void* buf, size_t bufSize)
{
	SET_SCOPE;
	if (index >= mEntries.size()) {
		RETURN false;
	}

	if (offset + bufSize > mEntries[index].fileSize) {
		RETURN false;
	}

	// todo: decode if packed?
	if (mEntries[index].fileSize != mEntries[index].packedSize) {
	}

	size_t read = mMb.read(mEntries[index].fileOffset, bufSize, (char*) buf);
	if (read == bufSize) {
		RETURN true;
	} else {
		RETURN false;
	}
}
