#pragma once

#include "BK_Util.h"

enum class AbstractRecordType : int
{
	UP = 0,
	DIR,
	LINK,
	LOGDSK,
	FILE
};

static const std::wstring g_strDir = L"<Папка>";
static const std::wstring g_strUp = L"<Вверх>";
static const std::wstring g_strLink = L"<Ссылка>";

static const std::wstring g_strBinExt = L".bin";

constexpr auto KNOWN_EXTS = 3;
constexpr auto BIN_EXT_IDX = 0; //индекс в массиве
static const std::wstring g_pstrExts[KNOWN_EXTS] =
{
	L".dsk",
	L".img",
	L".bkd"
};

#define COPY_BLOCK_SIZE 65536

enum class IMAGE_ERROR : int
{
	OK_NOERRORS = 0,        //нет ошибок
	NOT_ENOUGHT_MEMORY,     //Недостаточно памяти.
	IMAGE_CANNOT_OPEN,      //Невозможно открыть файл образа
	FILE_CANNOT_CREATE,     //Невозможно создать файл
	IMAGE_NOT_OPEN,         //Файл образа не открыт
	IMAGE_WRITE_PROTECRD,   //Файл образа защищён от записи.
	IMAGE_CANNOT_SEEK,      //Ошибка позиционирования в файле образа
	IMAGE_CANNOT_READ,      //Ошибка чтения файла образа
	IMAGE_CANNOT_WRITE,     //Ошибка записи в файл образа
	FS_CANNOT_CREATE_DIR,   //Невозможно создать директорию
	FS_FILE_NOT_FOUND,      //Файл(запись о файле в каталоге не найдена)
	FS_FORMAT_ERROR,        //ошибка в формате файловой системы
	FS_FILE_EXIST,          //Файл с таким именем уже существует.
	FS_DIR_EXIST,           //Директория с таким именем уже существует.
	FS_DIR_NOT_EXIST,       //Директории с таким именем не существует.
	FS_CAT_FULL,            //Каталог заполнен.
	FS_DISK_FULL,           //Диск заполнен.
	FS_DISK_NEED_SQEEZE,    //Диск сильно фрагментирован, нужно провести сквизирование.
	FS_DIR_NOT_EMPTY,       //Директория не пуста.
	FS_STRUCT_ERR,          //Нарушена структура каталога.
	FS_IS_NOT_DIR,          //Это не директория. - попытка подсунуть файл функции change dir
	FS_IS_NOT_FILE,         //Это не файл. - попытка подсунуть не файл функции, работающей с файлами
	FS_NOT_SUPPORT_DIRS,    //Файловая система не поддерживает директории.
	FS_FILE_PROTECTED,      //Файл защищён от удаления
	FS_DIR_DUPLICATE,       //встретилось дублирование номеров директорий
	FS_DIRNUM_FULL,         //закончились номера для директорий

	NUMBERS
};

extern std::wstring g_ImageErrorStr[];

static const std::wstring tblStrRec[3] =
{
	L"ь", L"и", L"ей"
};
static const std::wstring tblStrBlk[3] =
{
	L"", L"а", L"ов"
};

struct PaneInfo
{
	int nParentDir;
	int nCurDir;
	int nCurItem;
	std::wstring strCurrPath;    //текущий путь.
	PaneInfo()
	{
		clear();
	}
	void clear()
	{
		strCurrPath = L"/";
		nCurItem = nCurDir = 0;
		nParentDir = -1;
	}
};

enum FR_ATTR : uint32_t
{
	READONLY    = 0x01,
	HIDDEN      = 0x02,
	PROTECTED   = 0x04,
	VOLUMEID    = 0x08,
	DIR         = 0x10,
	ARCHIVE     = 0x20,
	TEMPORARY   = 0x40,
	LOGDISK     = 0x80,
	LINK        = 0x100,
	BAD         = 0x200,
	DELETED     = 0x400
};

constexpr auto SPECIFIC_DATA_BUFFER_LENGTH = 64;

struct AbstractFileRecord
{
	std::wstring strName;       //имя
	unsigned int nAttr;         //атрибуты, ну там директория, защищённый, скрытый, удалённый, плохой
	AbstractRecordType nRecType; //тип записи: 0="..", 1=директория, 2=ссылка, 3=логический диск, 4=простой файл, вводится специально для сортировки
	//поэтому частично дублирует атрибуты
	int nDirBelong;             //номер каталога, к которому принадлежит файл для файла и директории
	int nDirNum;                //номер директории для директории, 0 - для файла
	UINT nAddress;              //адрес файла, для директории 0, если для директории не 0, то это ссылка на другой диск.
	UINT nSize;                 //размер файла
	int nBlkSize;               //размер в блоках, или кластерах (для андос)
	UINT nStartBlock;           //начальный сектор/блок/кластер
	bool bSelected;             //вводим флаг, что запись в списке выделена.
	time_t timeCreation;        //для ФС умеющих хранить дату создания файла
	//здесь будем хранить оригинальную запись о файле.
	uint32_t nSpecificDataLength; //размер записи о файле. на БК они гарантированно меньше SPECIFIC_DATA_BUFFER_LENGTH байтов
	uint8_t pSpecificData[SPECIFIC_DATA_BUFFER_LENGTH]; //буфер данных

	AbstractFileRecord()
	{
		clear();
	}
	~AbstractFileRecord()
	{
		this->strName.erase();
	}
	void clear()
	{
		this->strName.erase();
		this->nAttr = 0;
		this->nStartBlock = this->nBlkSize = this->nSize = this->nAddress = this->nDirNum = this->nDirBelong = 0;
		this->nRecType = AbstractRecordType::UP;
		this->bSelected = false;
		this->nSpecificDataLength = 0;
		this->timeCreation = 0;
		memset(this->pSpecificData, 0, SPECIFIC_DATA_BUFFER_LENGTH);
	}
	AbstractFileRecord(const AbstractFileRecord *src)
	{
		this->strName = src->strName;
		this->nAttr = src->nAttr;
		this->nRecType = src->nRecType;
		this->nDirBelong = src->nDirBelong;
		this->nDirNum = src->nDirNum;
		this->nAddress = src->nAddress;
		this->nSize = src->nSize;
		this->nBlkSize = src->nBlkSize;
		this->nStartBlock = src->nStartBlock;
		this->bSelected = src->bSelected;
		this->timeCreation = src->timeCreation;
		this->nSpecificDataLength = src->nSpecificDataLength;
		memcpy(this->pSpecificData, src->pSpecificData, SPECIFIC_DATA_BUFFER_LENGTH);
	}
	AbstractFileRecord &operator = (const AbstractFileRecord &src)
	{
		this->strName = src.strName;
		this->nAttr = src.nAttr;
		this->nRecType = src.nRecType;
		this->nDirBelong = src.nDirBelong;
		this->nDirNum = src.nDirNum;
		this->nAddress = src.nAddress;
		this->nSize = src.nSize;
		this->nBlkSize = src.nBlkSize;
		this->nStartBlock = src.nStartBlock;
		this->bSelected = src.bSelected;
		this->timeCreation = src.timeCreation;
		this->nSpecificDataLength = src.nSpecificDataLength;
		memcpy(this->pSpecificData, src.pSpecificData, SPECIFIC_DATA_BUFFER_LENGTH);
		return *this;
	}
};

struct DiskCatalog
{
	std::vector<AbstractFileRecord> vecFC; //текущий каталог
	std::vector<int>vecDir;  //вектор номеров вложенных каталогов.
	int nCurrDirNum;    //номер текущего каталога.
	bool bHasDir;       //флаг, имеет ли файловая система директории
	bool bTrueDir;      // флаг, что файловая система имеет настояшие директории, как в MS-DOS например
	uint8_t nMaxDirNum; //максимальный номер директории для заданной ОС
	uint8_t arDirNums[256]; //список номеров директорий, найденных в каталоге. нужно, чтобы создавать новые директории.
	//переменные для отображения информации о ФС диска
	int nTotalRecs;     //всего записей в каталоге
	int nTotalBlocks;   //общее количество блоков/кластеров (зависит от ФС)
	int nFreeRecs;      //количество свободных записей в каталоге
	int nFreeBlocks;    //количество свободных блоков/кластеров (зависит от ФС) на основе чего высчитывается кол-во свободных байтов
	int nDataBegin;     //блок, с которого начинаются данные на диске (зависит от ФС)
	DiskCatalog() : nCurrDirNum(0), bHasDir(false), bTrueDir(false), nMaxDirNum(255), nTotalRecs(0), nTotalBlocks(0), nFreeRecs(0), nFreeBlocks(0), nDataBegin(0)
	{
		memset(&arDirNums[0], 0, 256);
	}
};


//получим номер окончания слова в зависимости от числа num
uint32_t GetWordEndIdx(uint32_t num);

