#pragma once

//#include <fstream>
#include "XString.h"

#undef DeleteFile

#define OT_READ		 0x01
#define OT_WRITE     0x02
#define OT_APPAND    0x04
#define OT_PLUS		 0x08

#define FS_DELETED 0x00	//or unallocated
#define FS_VALID   0x01 //there is 
#define FS_OPENED  0x03

#define CL_ENDOFFILE 0xffffffff
#define CL_UNUSED	 0x00000000

struct FILEINFO
{
	unsigned char State;//
	char Name[23];//filename
	unsigned long ATStart;//index of first block in at
	unsigned long Size;//size in byte
};

class Archive;

class ArchiveFile
{
	Archive*		m_Archive;
	unsigned long 	m_FIIndex;
	unsigned long 	m_FPos; //read/wirte pos in file
	unsigned long 	m_iCluster; //read/write cluster
	unsigned char 	m_OpenFlags;

	unsigned long AppandCluster(void);

protected:

	friend Archive;

	ArchiveFile(Archive*archive, unsigned long FIIndex, unsigned char openflags);

public:

	//CloseFile
	~ArchiveFile(void);
	
	bool EoF(void);
	void Seek(unsigned long pos);
	void Write(const void* data, unsigned long size);
	void Read(void* data, unsigned long size);
};

class Archive
{
	friend ArchiveFile;

	struct ARCHIVEINFO
	{
		unsigned long  ClusterSize;//Size of a cluster;
		unsigned long  Files;//number of files;
		unsigned long  FTSize;//length of file table
		unsigned long  ATSize;//length of allocation table
		unsigned long  Clusters;//number of clusters (length of allocation table) (first 2 entries are (first FT cluster and first AT cluster)
	}m_Info;

	XString			m_Filename;
	unsigned long	m_ClusterOffset;

	unsigned long*	m_AT;//keeps allocation table in memory
	FILEINFO*		m_FT;//keeps file table in memory
	
	FILE*		m_File;

	void AddCluster(void);
	void ExtendAT(void);//reserves a new cluster for AT
	void ExtendFT(void);//reserves a new cluster for FT
	unsigned long FindUnusedCluster(void);
	unsigned long FindUnusedFileInfo(void);
	void WriteFTItemChanges(unsigned long index);
	void WriteATItemChanges(unsigned long index);

public:
	//opens an archive
	Archive(XString fn);
	//creates and opens an archive
	Archive(unsigned char ClusterSizeExp, XString fn);
	//closes archive
	~Archive(void);

	ArchiveFile* OpenFile(XString fn, unsigned char openflags);
	void DeleteFile(XString fn);

	void Defragment(void);
};
