/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef _7ZIP_ARCHIVE_H
#define _7ZIP_ARCHIVE_H

extern "C" {
#include "lib/7z/7zTypes.h"
#include "lib/7z/7zFile.h"
#include "lib/7z/7z.h"
}

#include <vector>
#include <string>
#include "IArchive.h"

/**
 * An LZMA/7zip compressed, single-file archive.
 */
class CSevenZipArchive : public IArchive
{
public:
	explicit CSevenZipArchive(const std::string& name);
	virtual ~CSevenZipArchive();

	virtual unsigned int NumFiles() const override;
	virtual bool GetFile(unsigned int fid, std::vector<unsigned char>& buffer) override;
	virtual void FileInfo(unsigned int fid, std::string& name, int& size, int& mode) const override;
	virtual unsigned GetCrc32(unsigned int fid);

private:
	UInt32 blockIndex = 0xFFFFFFFF;
	Byte* outBuffer = nullptr;
	size_t outBufferSize = 0;

	struct FileData
	{
		int fp;
		/**
     * Real/unpacked size of the file in bytes.
     * @see #unpackedSize
     * @see #packedSize
     */
		int size;
		std::string origName;
		unsigned int crc;
		/**
     * How many bytes of files have to be unpacked to get to this file.
     * This either equal to size, or is larger, if there are other files
     * in the same solid block.
     * @see #size
     * @see #packedSize
     */
		int unpackedSize;
		/**
     * How many bytes of the archive have to be read
     * from disc to get to this file.
     * This may be smaller or larger then size,
     * and is smaller then or equal to unpackedSize.
     * @see #size
     * @see #unpackedSize
     */
		int packedSize;
		/**
     * file mode
     */
		int mode;
	};
	int GetFileName(const CSzArEx* db, int i);
	const char* GetErrorStr(int res);

	std::vector<FileData> fileData;
	UInt16* tempBuf = nullptr;
	size_t tempBufSize = 0;

	CFileInStream archiveStream;
	CSzArEx db;
	CLookToRead2 lookStream;
	ISzAlloc allocImp;
	ISzAlloc allocTempImp;

	bool isOpen;
};

#endif // _7ZIP_ARCHIVE_H
