/******************************************************************************
*	File		-	binary_file_buffer.cpp
*	Author		-	Joey Pollack
*	Date		-	2020/01/24 (y/m/d)
*	Mod Date	-	2020/01/24 (y/m/d)
*	Description	-	Reads an entire binary file into memory and allows for
*					extracting the data in chunks. Much faster than reading
*					large files chunk by chunk.
******************************************************************************/

#include "binary_file_buffer.h"
#include <fstream>
#include <string.h>

namespace lunarium
{
	BinaryFileBuffer::BinaryFileBuffer()
		:	mbIsLoaded(false), mpData(nullptr), mFileSize(0), mReadPos(0), mFileName("")
	{
	}

	BinaryFileBuffer::~BinaryFileBuffer()
	{
		Unload();
	}

	bool BinaryFileBuffer::LoadFile(const char * filename)
	{
		if (mbIsLoaded)
		{
			return false;
		}

		std::ifstream ifs(filename, std::ios_base::binary);
		if (!ifs.is_open())
		{
			return false;
		}

		int start = ifs.tellg();
		ifs.seekg(0, std::ios_base::end);
		int end = ifs.tellg();
		ifs.seekg(0, std::ios_base::beg);
		
		mFileSize = end - start;
		mpData = new unsigned char[mFileSize];

		ifs.read((char*)mpData, mFileSize);

		ifs.close();
		ifs.clear();

		mFileName = filename;
		mbIsLoaded = true;
		return true;
	}

	void BinaryFileBuffer::Unload()
	{
		if (!mbIsLoaded)
			return;

		delete[] mpData;
		mpData = nullptr;

		mFileSize = 0;
		mFileName = "";
		mReadPos = 0;
		mbIsLoaded = false;
	}

	bool BinaryFileBuffer::IsLoaded() const
	{
		return mbIsLoaded;
	}

	const std::string& BinaryFileBuffer::LoadedFileName() const
	{
		return mFileName;
	}

	int BinaryFileBuffer::GetFileSize() const
	{
		return mFileSize;
	}
	
	const unsigned char* BinaryFileBuffer::GetBuffer() const
	{
		return mpData;
	}

	bool BinaryFileBuffer::Read(char * buffer, int numBytes)
	{
		if (!mbIsLoaded || mReadPos >= mFileSize)
			return false;

		memcpy(buffer, &mpData[mReadPos], numBytes);
		mReadPos += numBytes;

		return true;
	}

	void BinaryFileBuffer::SeekTo(int pos)
	{
		mReadPos = pos;

		if (mReadPos < 0)
			mReadPos = 0;

		if (mReadPos >= mFileSize)
			mReadPos = mFileSize - 1;
	}

}