#pragma once

#include "ImgUtil.h"
#include "resource.h"
#include "BKParseImage.h"
#include "BKDEDefines.h"

class CBKFloppyImage_Prototype
{
	public:
		const wchar_t *m_pKoi8tbl;

	protected:
		bool m_bMakeAdd;        //флаг, реализованы ли функции добавления
		bool m_bMakeDel;        //флаг, реализованы ли функции удаления
		bool m_bMakeRename;     //флаг, реализованы ли функции переименования

		IMAGE_ERROR m_nLastErrorNumber;
		CBKImgFile  m_pFoppyImgFile;    //файл образа
		bool        m_bFileROMode;      //режим открытия образа, только для чтения == true. или для чтения/записи == false

		PARSE_RESULT m_sParseImgResult; //структура с параметрами

		DiskCatalog m_sDiskCat;         //структура, куда собрано всё, что касается каталога

		int         m_nBlockSize;      //Размер блока в байтах, обычно совпадает с сектором
		uint8_t     m_nSector[BLOCK_SIZE];
		uint8_t     m_mBlock[COPY_BLOCK_SIZE];
		int         m_nSeekOffset;
		//переменные для GetStartFileName/GetNextFileName
		std::vector<int> m_vecPC; //список позиций для поиска в каталоге, для того, чтобы рекурсивные алгоритмы обхода каталога работали
		int m_nCatPos;    //глобальная позиция для поиска в каталоге

		void        MakeFakeOutDirRecord();

		/* Перемещение к заданному блоку образа */
		bool        SeekToBlock(size_t nBlockNumber);
		/* чтение данных */
		bool        ReadData(void *ptr, size_t length);
		/* Перемещение к заданному блоку образа и чтение данных */
		bool        SeektoBlkReadData(size_t nBlockNumber, void *ptr, size_t length);
		/* запись данных */
		bool        WriteData(void *ptr, size_t length);
		/* Перемещение к заданному блоку образа и запись данных */
		bool        SeektoBlkWriteData(size_t nBlockNumber, void *ptr, size_t length);

		/* преобразование абстрактной записи в конкретную. Реализация зависит от ОС */
		virtual void ConvertAbstractToRealRecord(AbstractFileRecord *pFR, bool bRenameOnly = false) {}
		virtual void ConvertRealToAbstractRecord(AbstractFileRecord *pFR) {}

	public:
		CBKFloppyImage_Prototype(const PARSE_RESULT &image);
		virtual ~CBKFloppyImage_Prototype();

		/* открыть образ */
		bool OpenFloppyImage();
		/* закрыть образ */
		void CloseFloppyImage();
		/* переоткрыть заново */
		bool ResetFloppyImage();

		inline std::vector<AbstractFileRecord> *CurrDirectory()
		{
			return & m_sDiskCat.vecFC;
		}
		inline const int GetCurrDirNum() //специальный костыль. чтобы узнавать о выходе из лог диска
		{
			return m_sDiskCat.nCurrDirNum;
		}
		inline const std::wstring &GetCurrImgName()
		{
			return m_sParseImgResult.strName;
		}
		inline bool GetImageOpenStatus()
		{
			return m_bFileROMode;
		}
		inline unsigned long GetBaseOffset()
		{
			return m_sParseImgResult.nBaseOffset;
		}
		inline unsigned long GetImgSize()
		{
			return m_sParseImgResult.nImageSize;
		}
		inline IMAGE_TYPE GetImgOSType()
		{
			return m_sParseImgResult.imageOSType;
		}
		inline bool isImageBootable()
		{
			return m_sParseImgResult.bImageBootable;
		}
		inline IMAGE_ERROR GetErrorNumber()
		{
			return m_nLastErrorNumber;
		}

		void EnableGUIControls();

		size_t EvenSizeByBlock(size_t length)
		{
			return (length) ? (((length - 1) | (BLOCK_SIZE - 1)) + 1) : 0; //размер проги выровняем по границе сектора
		}

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

		//получение данных специфических для заданной ОС
		//возвращает 0, если спец данных нету, или ID строки в файле ресурсов, если есть. Предполагается, что ID не может быть 0
		virtual UINT HasSpecificData() const
		{
			return 0;
		}
		virtual const std::wstring GetSpecificData(AbstractFileRecord *fr)
		{
			return L"";
		}

		virtual const std::wstring GetImageInfo();

		virtual const size_t GetImageFreeSpace();


		/* прочитать каталог образа */
		virtual bool ReadCurrentDir();
		/* записать каталог образа */
		virtual bool WriteCurrentDir();
		/* прочитать файл из образа */
		virtual bool ReadFile(AbstractFileRecord *pFR, uint8_t *pBuffer)
		{
			return false;
		}
		//специально для ксидос вводим перехватчик,
		//который будет модифицировать имя файла
		virtual void OnExtract(AbstractFileRecord *pFR, std::wstring &strName)
		{
		}
		/* записать файл в образ */
		virtual bool WriteFile(AbstractFileRecord *pFR, uint8_t *pBuffer)
		{
			return false;
		}
		/* удалить файл в образе */
		virtual bool DeleteFile(AbstractFileRecord *pFR, bool bForce = false)
		{
			return false;
		}
		/* сменить текущую директорию в образе */
		virtual bool ChangeDir(AbstractFileRecord *pFR);
		/* проверить, существует ли такая директория в образе */
		virtual bool VerifyDir(AbstractFileRecord *pFR);
		/* создать директорию в образе */
		virtual bool CreateDir(AbstractFileRecord *pFR);
		/* удалить директорию в образе */
		virtual bool DeleteDir(AbstractFileRecord *pFR);

		/*поиск и выдача всех найденных записей о файлах в текущей директории
		Вход: pFR указатель на существующий экземпляр записи
		Выход: true - найдено, при этом pFR - структура заполнена данными
		false - не найдено, pFR обнулена
		*/
		virtual bool GetStartFileName(AbstractFileRecord *pFR);
		virtual bool GetNextFileName(AbstractFileRecord *pFR);

		virtual bool RenameRecord(AbstractFileRecord *pFR)
		{
			return false;
		}
};

