#pragma once
#include <new>
#include "bootpack.h"
#include "ata/ataio.h"
#include "typedefs.h"
#include "fat32.h"

class FileSystem{
public:
	static void Init(BOOTINFO *binfo);
	
	static FileSystem &Inst(){
		return *(FileSystem *)buf;
	}
	
	class File{
	public:
		File(FileSystem *fs, const wchar_t *filename, DIRENT *ent, DWORD pos);
		
		enum class SEEK_ORG{
			SET,CUR,END
		};
		int Seek(DWORD offset, SEEK_ORG seekorg);
		int Read(BYTE *buf, int len);
		DWORD Size(){
			return size;
		}
	private:
		DWORD size;
		DWORD curpos;
		DWORD curclus;
		DWORD startclus;
		wchar_t *filename;
		static const DWORD INVLID_CLUS = 0xffffffff;

		FileSystem *fs;
		void reload_curclus();

	};
	DWORD getclustersize()const;
	DWORD firstdatasector()const;
	DWORD getsectorbyclus(DWORD clus)const;

	DWORD getcluscountbysize(DWORD size)const;
	DWORD getclusindexbysize(DWORD size)const;
	DWORD getfatsector(DWORD n = 0)const;

	File *CreateFile(
		const wchar_t *filename,
		DWORD  dwAccess,             // アクセス指定
		DWORD  dwShare,              // 共有方法
		DWORD psa,    // セキュリティ属性
		DWORD  dwCreateDisposition,  // 動作指定
		DWORD  dwFlagsAndAttributes, // フラグと属性
		HANDLE hTemplate             // テンプレートファイル
	);
private:
	static BYTE buf[];
	static void* operator new(size_t size, void* pbuf){ return pbuf; }
	FileSystem(BOOTINFO *binfo);
	
	void ClearTrace( void );
	void pause();
	void ShowAll( void );
	
	int ReadSector(int dev, int sectorcount, QWORD lba, BYTE *buf, int bufsize, int numsect);

	static const int pat_index = 0;
	BOOTINFO *binfo;
	int m_drivenum;
	static const int READBUFSIZE = 4096;
	BYTE readbuf[READBUFSIZE];
	MBR_SECTOR mbr;

	//----------------------FAT32------------------------
	FAT32_BOOTSECTOR bootsect;
	struct FILEHANDLE{
		bool used;
		wchar_t *filename;

	};

	int FileList(DWORD dirclus);
	int ReadCluster(int clusternum);
	static void ConvertShortName(char *dest, const char *name);
	DWORD GetNextCluster(DWORD clus);

	bool FindEnt(DWORD dirclus, const wchar_t *finding, DIRENT *fdirent);
};

