#pragma once

#include "BK_Util.h"

typedef enum
{
	RECORD_TYPE_UP = 0,
	RECORD_TYPE_DIR,
	RECORD_TYPE_LINK,
	RECORD_TYPE_LOGDSK,
	RECORD_TYPE_FILE
} AbstractRecordType;

#define COPY_BLOCK_SIZE 65536

typedef enum
{
	IMAGE_ERROR_OK = 0, //нет ошибок
	IMAGE_ERROR_NOT_ENOUGHT_MEMORY, //Недостаточно памяти.
	IMAGE_ERROR_FILE_CANNOT_OPEN,   //Невозможно открыть файл образа
	IMAGE_ERROR_FILE_CANNOT_CREATE, //Невозможно создать файл образа
	IMAGE_ERROR_FILE_NOT_OPEN,      //Файл образа не открыт
	IMAGE_ERROR_FILE_WRITE_PROTECRD, //Файл образа защищён от записи.
	IMAGE_ERROR_CANNOT_SEEK_FILE,   //Ошибка позиционирования в файле образа
	IMAGE_ERROR_CANNOT_READ_FILE,   //Ошибка чтения файла образа
	IMAGE_ERROR_CANNOT_WRITE_FILE,  //Ошибка записи в файл образа
	IMAGE_ERROR_CANNOT_CREATE_DIR,  //Невозможно создать директорию
	IMAGE_ERROR_FILE_NOT_FOUND,     //Файл(запись о файле в каталоге не найдена)
	IMAGE_ERROR_FS_FORMAT_ERROR,    //ошибка в формате файловой системы
	IMAGE_ERROR_FS_FILE_EXIST,      //Файл с таким именем уже существует.
	IMAGE_ERROR_FS_DIR_EXIST,       //Директория с таким именем уже существует.
	IMAGE_ERROR_FS_DIR_NOT_EXIST,   //Директории с таким именем не существует.
	IMAGE_ERROR_FS_CAT_FULL,        //Каталог заполнен.
	IMAGE_ERROR_FS_DISK_FULL,       //Диск заполнен.
	IMAGE_ERROR_FS_DISK_FULL_SQEEZE,    //Диск сильно фрагментирован, нужно провести сквизирование.
	IMAGE_ERROR_FS_DIR_NOT_EMPTY,   //Директория не пуста.
	IMAGE_ERROR_FS_STRUCT_ERR,      //Нарушена структура каталога.
	IMAGE_ERROR_IS_NOT_DIR,         //Это не директория. - попытка подсунуть файл функции change dir
	IMAGE_ERROR_IS_NOT_FILE,        //Это не файл. - попытка подсунуть не файл функции, работающей с файлами
	IMAGE_ERROR_FS_NOT_SUPPORT_DIRS, //Файловая система не поддерживает директории.
	IMAGE_ERROR_FS_FILE_PROTECTED,  //Файл защищён от удаления
	IMAGE_ERROR_NUMBER
} IMAGE_ERROR_NUMS;

extern wstring g_ImageErrorStr[];

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

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

#define FR_ATTR_READONLY 0x01
#define FR_ATTR_HIDDEN 0x02
#define FR_ATTR_PROTECTED 0x04
#define FR_ATTR_VOLUMEID 0x08
#define FR_ATTR_DIR 0x10
#define FR_ATTR_ARCHIVE 0x20
#define FR_ATTR_TEMPORARY 0x40
#define FR_ATTR_LOGDISK 0x80
#define FR_ATTR_LINK 0x100
#define FR_ATTR_BAD 0x200
#define FR_ATTR_DELETED 0x400


#define SPECIFIC_DATA_BUFFER_LENGTH 128
struct AbstractFileRecord
{
	wstring strName;            //имя
	unsigned int nAttr;         //атрибуты, ну там директория, защищённый, скрытый, удалённый, плохой
	AbstractRecordType nRecType;    //тип записи: 0="..", 1=директория, 2=ссылка, 3=логический диск, 4=простой файл, вводится специально для сортировки
	//поэтому частично дублирует атрибуты
	int nDirBelong;             //номер каталога, к которому принадлежит файл для файла и директории
	int nDirNum;                //номер директории для директории, 0 - для файла
	unsigned int nAddress;      //адрес файла, для директории 0, если для директории не 0, то это ссылка на другой диск.
	unsigned int nSize;         //размер файла
	int nBlkSize;               //размер в блоках, или кластерах (для андос)
	unsigned int nStartBlock;   //начальный сектор/блок/кластер
	bool bSelected;             //вводим флаг, что запись в списке выделена.
	time_t timeCreation;        //для ФС умеющих хранить дату создания файла
	//здесь будем хранить оригинальную запись о файле.
	uint32_t nSpecificDataLength; //размер записи о файле. на БК они гарантированно меньше 128 байтов
	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 = RECORD_TYPE_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
{
	vector<AbstractFileRecord> vecFC; //текущий каталог
	vector<int>vecDir;  //вектор номеров вложенных каталогов.
	int nCurrDirNum;    //номер текущего каталога.
	bool bHasDir;       //флаг, имеет ли файловая система директории
	int nMaxDirNum;     //максимальный номер директории на диске. нужно, чтобы создавать новые директории.
	//переменные для отображения информации о ФС диска
	int nTotalRecs;     //всего записей в каталоге
	int nTotalBlocks;   //общее количество блоков/кластеров (зависит от ФС)
	int nFreeRecs;      //количество свободных записей в каталоге
	int nFreeBlocks;    //количество свободных блоков/кластеров (зависит от ФС) на основе чего высчитывается кол-во свободных байтов
	int nDataBegin;     //блок, с которого начинаются данные на диске (зависит от ФС)
};


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

