#pragma once

using namespace std;
#include <vector>

#define FR_ATTR_PROTECTED 1
#define FR_ATTR_HIDDEN 2
#define FR_ATTR_DELETED 4
#define FR_ATTR_BAD 8
#define FR_ATTR_TEMPORARY 0x10
#define FR_ATTR_LOGDISK 0x20
#define FR_ATTR_LINK 0x40
#define FR_ATTR_DIR 0x80

#define RECORD_TYPE_UP 0
#define RECORD_TYPE_DIR 1
#define RECORD_TYPE_LINK 2
#define RECORD_TYPE_LOGDSK 3
#define RECORD_TYPE_FILE 4

#define COPY_BLOCK_SIZE 4096

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_CANNOT_SEEK_FILE,   //Ошибка позиционирования в файле
	IMAGE_ERROR_CANNOT_READ_FILE,   //Ошибка чтения файла
	IMAGE_ERROR_CANNOT_WRITE_FILE,  //Ошибка записи в файл
	IMAGE_ERROR_CANNOT_CREATE_DIR,  //Невозможно создать директорию
	IMAGE_ERROR_FS_FORMAT_ERROR     //ошибка в формате файловой системы

} IMAGE_ERROR_NUMS;

extern CString g_ImageErrorStr[];

// это правильная таблица
static const TCHAR koi8tbl_RFC1489[128] =
{
	//{200..237}
	0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
	0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
	0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248,
	0x2264, 0x2265, 0xA0,   0x2321, 0xB0,   0xB2,   0xB7,   0xF7,
	//{240..277}
	0x2550, 0x2551, 0x2552, 0x451,  0x2553, 0x2554, 0x2555, 0x2556,
	0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E,
	0x255F, 0x2560, 0x2561, 0x401,  0x2562, 0x2563, 0x2564, 0x2565,
	0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0xA9,
	//{300..337}
	_T('ю'), _T('а'), _T('б'), _T('ц'), _T('д'), _T('е'), _T('ф'), _T('г'),
	_T('х'), _T('и'), _T('й'), _T('к'), _T('л'), _T('м'), _T('н'), _T('о'),
	_T('п'), _T('я'), _T('р'), _T('с'), _T('т'), _T('у'), _T('ж'), _T('в'),
	_T('ь'), _T('ы'), _T('з'), _T('ш'), _T('э'), _T('щ'), _T('ч'), _T('ъ'),
	//{340..377}
	_T('Ю'), _T('А'), _T('Б'), _T('Ц'), _T('Д'), _T('Е'), _T('Ф'), _T('Г'),
	_T('Х'), _T('И'), _T('Й'), _T('К'), _T('Л'), _T('М'), _T('Н'), _T('О'),
	_T('П'), _T('Я'), _T('Р'), _T('С'), _T('Т'), _T('У'), _T('Ж'), _T('В'),
	_T('Ь'), _T('Ы'), _T('З'), _T('Ш'), _T('Э'), _T('Щ'), _T('Ч'), _T('Ъ')
};


// это таблица кои8 БК11М
//таблица соответствия верхней половины аскии кодов с 128 по 255, включая псевдографику.
//выяснилось, что на бк11 таблица тоже нестандартная, но от бк10 тоже отличается.
static const TCHAR koi8tbl11M[128] =
{
	//{200..237}
	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
	0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
	0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
	0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
	//{240..277}
	0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
	0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
	0x25ba, 0x25c4, 0x2195, 0x203c, 0xb6,   0xa7,   0x25ac, 0x21a8,
	0x2191, 0x2193, 0x2192, 0x2190, 0x2fe,  0x2194, 0x25b2, 0x25bc,
	//{300..337}
	_T('ю'), _T('а'), _T('б'), _T('ц'), _T('д'), _T('е'), _T('ф'), _T('г'),
	_T('х'), _T('и'), _T('й'), _T('к'), _T('л'), _T('м'), _T('н'), _T('о'),
	_T('п'), _T('я'), _T('р'), _T('с'), _T('т'), _T('у'), _T('ж'), _T('в'),
	_T('ь'), _T('ы'), _T('з'), _T('ш'), _T('э'), _T('щ'), _T('ч'), _T('ъ'),
	//{340..377}
	_T('Ю'), _T('А'), _T('Б'), _T('Ц'), _T('Д'), _T('Е'), _T('Ф'), _T('Г'),
	_T('Х'), _T('И'), _T('Й'), _T('К'), _T('Л'), _T('М'), _T('Н'), _T('О'),
	_T('П'), _T('Я'), _T('Р'), _T('С'), _T('Т'), _T('У'), _T('Ж'), _T('В'),
	_T('Ь'), _T('Ы'), _T('З'), _T('Ш'), _T('Э'), _T('Щ'), _T('Ч'), _T('Ъ')
};

//таблица соответствия верхней половины аскии кодов с 128 по 255, включая псевдографику
static const TCHAR koi8tbl10[128] =
{
	//{200..237} этих символов на бк10 нету.
	_T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '),
	_T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '),
	_T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '),
	_T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '), _T(' '),
	//{240..277}
	0xb6,    0x2534,  0x2665,  0x2510,  0x2561,  0x251c,  0x2514,  0x2550,
	0x2564,  0x2660,  0x250c,  0x252c,  0x2568,  0x2193,  0x253c,  0x2551,
	0x2524,  0x2190,  0x256c,  0x2191,  0x2663,  0x2500,  0x256b,  0x2502,
	0x2666,  0x2518,  0x256a,  0x2565,  0x2567,  0x255e,  0x2192,  0x2593,
	//{300..337}
	_T('ю'), _T('а'), _T('б'), _T('ц'), _T('д'), _T('е'), _T('ф'), _T('г'),
	_T('х'), _T('и'), _T('й'), _T('к'), _T('л'), _T('м'), _T('н'), _T('о'),
	_T('п'), _T('я'), _T('р'), _T('с'), _T('т'), _T('у'), _T('ж'), _T('в'),
	_T('ь'), _T('ы'), _T('з'), _T('ш'), _T('э'), _T('щ'), _T('ч'), _T('ъ'),
	//{340..377}
	_T('Ю'), _T('А'), _T('Б'), _T('Ц'), _T('Д'), _T('Е'), _T('Ф'), _T('Г'),
	_T('Х'), _T('И'), _T('Й'), _T('К'), _T('Л'), _T('М'), _T('Н'), _T('О'),
	_T('П'), _T('Я'), _T('Р'), _T('С'), _T('Т'), _T('У'), _T('Ж'), _T('В'),
	_T('Ь'), _T('Ы'), _T('З'), _T('Ш'), _T('Э'), _T('Щ'), _T('Ч'), _T('Ъ')
};

static const CString tblStrRec[3] =
{
	_T("ь"), _T("и"), _T("ей")
};
static const CString tblStrBlk[3] =
{
	_T(""), _T("а"), _T("ов")
};

struct PaneInfo
{
	int nParentDir;
	int nCurDir;
	int nCurItem;
	PaneInfo()
	{
		clear();
	}
	void clear(void)
	{
		nCurItem = nCurDir = nParentDir = 0;
	}
};

struct FileRecord
{
	CString strName;    //имя
	UINT nAttr;         //атрибуты, ну там директория, защищённый, скрытый, удалённый, плохой
	int nRecType;       //тип записи: 0="..", 1=директория, 2=ссылка, 3=логический диск, 4=простой файл, вводится специально для сортировки
	//поэтому частично дублирует атрибуты
	int nDirNum;        //номер каталога, к которому принадлежит файл для файла и директории
	int nDirDir;        //номер директории для директории, 0 - для файла
	int nAddress;       //адрес файла, для директории 0, если для директории не 0, то это ссылка на другой диск.
	int nSize;          //размер файла
	int nBlkSize;       //размер в блоках, или кластерах (для андос)
	int nStartSector;   //начальный сектор/блок/кластер
	DWORD nSpecificData; //данные, индивидуальные для каждой ОС.
	BOOL bSelected;     //вводим флаг, что запись в списке выделена.
	FileRecord()
	{
		clear();
	}
	~FileRecord()
	{
		this->strName.Empty();
	}
	void clear(void)
	{
		this->strName = _T("");
		this->nAttr = 0;
		this->nStartSector = this->nBlkSize = this->nSize = this->nAddress = this->nDirDir = this->nDirNum = this->nRecType = 0;
		this->nSpecificData = 0;
		this->bSelected = FALSE;
	}
	FileRecord(const FileRecord *src)
	{
		this->strName = src->strName;
		this->nAttr = src->nAttr;
		this->nRecType = src->nRecType;
		this->nDirNum = src->nDirNum;
		this->nDirDir = src->nDirDir;
		this->nAddress = src->nAddress;
		this->nSize = src->nSize;
		this->nBlkSize = src->nBlkSize;
		this->nStartSector = src->nStartSector;
		this->nSpecificData = src->nSpecificData;
		this->bSelected = src->bSelected;
	}
	FileRecord &operator = (const FileRecord &src)
	{
		this->strName = src.strName;
		this->nAttr = src.nAttr;
		this->nRecType = src.nRecType;
		this->nDirNum = src.nDirNum;
		this->nDirDir = src.nDirDir;
		this->nAddress = src.nAddress;
		this->nSize = src.nSize;
		this->nBlkSize = src.nBlkSize;
		this->nStartSector = src.nStartSector;
		this->nSpecificData = src.nSpecificData;
		this->bSelected = src.bSelected;
		return *this;
	}
};

struct DiskCatalog
{
	vector<FileRecord> vecFC; //каталог
	vector<UINT> vecPC; //список позиций для поиска в каталоге, для того, чтобы рекурсивные алгоритмы обхода каталога работали
	UINT nVectorPos;    //глобальная позиция для поиска в каталоге

	//переменные для отображения информации о ФС диска
	int nTotalRecs; //всего записей в каталоге
	int nTotalBlocks; //общее количество блоков/кластеров (зависит от ФС)
	int nFreeRecs; //количество свободных записей в каталоге
	int nFreeBlocks; //количество свободных блоков/кластеров (зависит от ФС) на основе чего высчитывается кол-во свободных байтов
};
//структура для передачи параметров анализатору файлов
struct AnalyseFileStr
{
	CFile file;
	BOOL bUseAsBin;
	CString strName;
	CString strExt;
	int nAddr;
	int nLen;
};


CString BKToUNICODE(BYTE *pBuff, int size, const TCHAR table[]);
TCHAR BKToUNICODE_Byte(BYTE b, const TCHAR table[]);

void UNICODEtoBK(const CString &ustr, BYTE *pBuff, int bufSize, BOOL bFillBuf = FALSE);

void SetSafeName(CString &str);
void SetSafeDir(CString &str);

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