#pragma once
#include "BKFloppyImage_Prototype.h"
//!!! Не работает, только начата работа.
#pragma pack(push)
#pragma pack(1)
struct MSDOSFileRecord
{
	uint8_t name[8];
	uint8_t ext[3];
	uint8_t attr;   // Байт по адресу 0x0B, отвечающий за атрибуты файла.
	uint8_t ntres;  // Байт по адресу 0x0C, используется в Windows NT.
	uint8_t create_time_tenth; // Байт по адресу 0x0D. Счётчик десятков миллисекунд времени создания файла, допустимы значения 0-199. Поле часто неоправданно игнорируется.
	uint16_t create_time;   //2 байта по адресу 0x0E. Время создания файла с точностью до 2 секунд.
	uint16_t create_date;   //2 байта по адресу 0x10. Дата создания файла.
	uint16_t last_access_date; //2 байта по адресу 0x12. Дата последнего доступа к файлу (то есть последнего чтения или записи — в последнем случае приравнивается DIR_WrtDate). Аналогичное поле для времени не предусмотрено.
	uint16_t first_cluster_hi; //2 байта по адресу 0x14. Номер первого кластера файла (старшее слово, на томе FAT12/FAT16 равен нулю).
	uint16_t wrt_time;  //2 байта по адресу 0x16. Время последней записи (модификации) файла, например, его создания.
	uint16_t wrt_date;  //2 байта по адресу 0x18. Дата последней записи (модификации) файла, в том числе создания.
	uint16_t first_cluster_lo; //2 байта по адресу 0x1A. Номер первого кластера файла (младшее слово).
	uint32_t length; //DWORD, содержащий значение размера файла в байтах. Фундаментальное ограничение FAT32 — максимально допустимое значение размера файла составляет 0xFFFFFFFF (то есть 4 Гб минус 1 байт).
	MSDOSFileRecord()
	{
		memset(this, 0, sizeof(MSDOSFileRecord));
	}
	MSDOSFileRecord &operator = (const MSDOSFileRecord &src)
	{
		memcpy(this, &src, sizeof(MSDOSFileRecord));
		return *this;
	}
	MSDOSFileRecord &operator = (const MSDOSFileRecord *src)
	{
		memcpy(this, src, sizeof(MSDOSFileRecord));
		return *this;
	}
};
#pragma pack(pop)

class CBKFloppyImage_MSDOS :
	public CBKFloppyImage_Prototype
{
		int         m_nClusterSectors;  //Количество секторов в кластере
		int         m_nClusterSize;     //размер кластера в байтах
		int         m_nBootSectors;     //Число секторов в загрузчике
		int         m_nRootFilesNum;    //Максимальное число файлов в корневом каталоге
		int         m_nRootSize;        //размер корневого каталога в байтах
		int         m_nFatSectors;      //Число секторов в одной фат
		int         m_nFatSize;         //размер одной фат в байтах
		uint8_t    *m_pFatTbl;
		//текущий каталог
		int         m_nCatCluster;      //номер кластера в буфере каталога (для подкаталогов, для корня - 0)
		int         m_nCatRootBlock;    //номер сектора в буфере для корневого каталога
		uint8_t    *m_pCatBuffer;       //буфер кластера каталога
		//вспомогательные переменные
		int         m_nRootSectorOffset;    //начало корневого каталога
		int         m_nDataSectorOffset;    //начало области данных
		//переменные для поиска записей в текущем каталоге
		int         m_nFindCatCluster;      //номер кластера в буфере каталога (для подкаталогов, для корня - 0)
		int         m_nFindCatRootBlock;    //номер сектора в буфере для корневого каталога
		uint8_t    *m_pFindCatBuffer;       //буфер кластера каталога
		int         m_nFindRecNum;          //счётчик записей в буфере

		int GetNextFat(int fat);
		int FindFreeFat(int fat);
		uint16_t SetFat(int fat, uint16_t val);

		/* поиск заданной записи в каталоге.
		делается поиск на полное бинарное соответствие
		выход: -1 если не найдено,
		номер записи в каталоге - если найдено.
		*/
		int FindRecord(MSDOSFileRecord *pMSFR);
		/* поиск заданной записи в каталоге.
		если bFull==false делается поиск по имени
		если bFull==true делается поиск по имени и другим параметрам
		выход: -1 если не найдено,
		номер записи в каталоге - если найдено.
		*/
		int FindRecord2(MSDOSFileRecord *pMSFR, bool bFull = true);

		bool SeekToCluster(int nCluster);

		/*
		выход:  true - запись выдана в pMSFR
		        false - каталог физически закончился или ошибка. pMSFR не определено
		*/
		MSDOSFileRecord *GetFirstRecord();
		MSDOSFileRecord *GetNextRecord();

	protected:
		virtual void ConvertAbstractToRealRecord(AbstractFileRecord *pFR, bool bRenameOnly = false) override;
		virtual void ConvertRealToAbstractRecord(AbstractFileRecord *pFR) override;

	public:
		CBKFloppyImage_MSDOS(const PARSE_RESULT &image);
		virtual ~CBKFloppyImage_MSDOS() override;

		//виртуальные функции

		virtual const wstring GetImageInfo() override;
		virtual const size_t GetImageFreeSpace() override;

		/* прочитать каталог образа.
		на выходе: заполненная структура m_sDiskCat */
		virtual bool ReadCurrentDir() override;
		/* записать каталог образа */
		virtual bool WriteCurrentDir() override;
		/* прочитать файл из образа
		* Параметры.
		* pFR - указатель на абстрактную запись о файле, внутри которой сохранена
		*       и реальная запись о файле, где сохранены все необходимые данные,
		*       даже с дублированием.
		* pBuffer - указатель на заранее выделенный массив памяти, куда будем сохранять файл.
		*   что мы будем делать потом с данными буфера, функцию не волнует. */
		virtual bool ReadFile(AbstractFileRecord *pFR, uint8_t *pBuffer) override;
		/* записать файл в образ
		* Параметры.
		* pFR - указатель на абстрактную запись о файле, внутри которой сформирована
		*       реальная запись о файле, где по возможности сохранены все необходимые данные для записи,
		*       даже с дублированием.
		* pBuffer - указатель на заранее выделенный массив памяти, где заранее подготовлен массив сохраняемого файла. */
		virtual bool WriteFile(AbstractFileRecord *pFR, uint8_t *pBuffer) override;
		/* удалить файл в образе
		* Параметры.
		* pFR - указатель на абстрактную запись о файле, внутри которой сохранена
		*       и реальная запись о файле, где сохранены все необходимые данные,
		*       даже с дублированием. */
		virtual bool DeleteFile(AbstractFileRecord *pFR, bool bForce = false) override;
		/* создать директорию в образе */
		virtual bool CreateDir(AbstractFileRecord *pFR) override;
		/* проверить, существует ли такая директория в образе */
		virtual bool VerifyDir(AbstractFileRecord *pFR) override;
		/* удалить директорию в образе */
		virtual bool DeleteDir(AbstractFileRecord *pFR) override;

		virtual bool GetStartFileName(AbstractFileRecord *pFR) override;
		virtual bool GetNextFileName(AbstractFileRecord *pFR) override;

		virtual bool RenameRecord(AbstractFileRecord *pFR) override;
};

