#pragma once

#include <string>

// это правильная таблица
static const wchar_t 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}
	L'ю', L'а', L'б', L'ц', L'д', L'е', L'ф', L'г',
	L'х', L'и', L'й', L'к', L'л', L'м', L'н', L'о',
	L'п', L'я', L'р', L'с', L'т', L'у', L'ж', L'в',
	L'ь', L'ы', L'з', L'ш', L'э', L'щ', L'ч', L'ъ',
	// {340..377}
	L'Ю', L'А', L'Б', L'Ц', L'Д', L'Е', L'Ф', L'Г',
	L'Х', L'И', L'Й', L'К', L'Л', L'М', L'Н', L'О',
	L'П', L'Я', L'Р', L'С', L'Т', L'У', L'Ж', L'В',
	L'Ь', L'Ы', L'З', L'Ш', L'Э', L'Щ', L'Ч', L'Ъ'
};


// это таблица кои8 БК11М
// таблица соответствия верхней половины аскии кодов с 128 по 255, включая псевдографику.
// выяснилось, что на бк11 таблица тоже нестандартная, но от бк10 тоже отличается.
static const wchar_t 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}
	L'ю', L'а', L'б', L'ц', L'д', L'е', L'ф', L'г',
	L'х', L'и', L'й', L'к', L'л', L'м', L'н', L'о',
	L'п', L'я', L'р', L'с', L'т', L'у', L'ж', L'в',
	L'ь', L'ы', L'з', L'ш', L'э', L'щ', L'ч', L'ъ',
	// {340..377}
	L'Ю', L'А', L'Б', L'Ц', L'Д', L'Е', L'Ф', L'Г',
	L'Х', L'И', L'Й', L'К', L'Л', L'М', L'Н', L'О',
	L'П', L'Я', L'Р', L'С', L'Т', L'У', L'Ж', L'В',
	L'Ь', L'Ы', L'З', L'Ш', L'Э', L'Щ', L'Ч', L'Ъ'
};

// таблица соответствия верхней половины аскии кодов с 128 по 255, включая псевдографику
static const wchar_t koi8tbl10[128] =
{
	// {200..237} этих символов на бк10 нету.
	L' ', L' ', L' ', L' ', L' ', L' ', L' ', L' ',
	L' ', L' ', L' ', L' ', L' ', L' ', L' ', L' ',
	L' ', L' ', L' ', L' ', L' ', L' ', L' ', L' ',
	L' ', L' ', L' ', L' ', L' ', L' ', L' ', L' ',
	// {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}
	L'ю', L'а', L'б', L'ц', L'д', L'е', L'ф', L'г',
	L'х', L'и', L'й', L'к', L'л', L'м', L'н', L'о',
	L'п', L'я', L'р', L'с', L'т', L'у', L'ж', L'в',
	L'ь', L'ы', L'з', L'ш', L'э', L'щ', L'ч', L'ъ',
	// {340..377}
	L'Ю', L'А', L'Б', L'Ц', L'Д', L'Е', L'Ф', L'Г',
	L'Х', L'И', L'Й', L'К', L'Л', L'М', L'Н', L'О',
	L'П', L'Я', L'Р', L'С', L'Т', L'У', L'Ж', L'В',
	L'Ь', L'Ы', L'З', L'Ш', L'Э', L'Щ', L'Ч', L'Ъ'
};

// структура для передачи параметров анализатору файлов
struct AnalyseFileStruct
{
	FILE *file;
	std::wstring strName;
	std::wstring strExt;
	int nAddr;
	int nLen;
	uint8_t OrigName[16];
	bool bIsCRC;
	uint16_t nCRC;
	AnalyseFileStruct() : file(nullptr), nAddr(0), nLen(0), OrigName{0}, bIsCRC(false), nCRC(0) {};
};


std::wstring BKToUNICODE(uint8_t *pBuff, const size_t size, const wchar_t table[]);
wchar_t BKToWIDEChar(const uint8_t b, const wchar_t table[]);

void UNICODEtoBK(const std::wstring &ustr, uint8_t *pBuff, const size_t bufSize, const bool bFillBuf = false);

std::wstring SetSafeName(const std::wstring &str);

// удаление заданного символа с обоих концов строки
std::wstring trim(const std::wstring &str, const wchar_t trim_char = L' ');
// удаление заданного символа в начале строки
std::wstring trimLeft(const std::wstring &str, const wchar_t trim_char = L' ');
// удаление заданного символа в конце строки
std::wstring trimRight(const std::wstring &str, const wchar_t trim_char = L' ');
// замена всех символов src в строке на символы dst
std::wstring replaceChar(const std::wstring &str, const wchar_t src, const wchar_t dst);
// замена всех символов, входящих в src в строке на символы dst
std::wstring replaceChars(const std::wstring &str, const std::wstring &src, const wchar_t dst);

std::wstring strToUpper(const std::wstring &str);
std::wstring strToLower(const std::wstring &str);


template<typename ... Args>
std::wstring string_format(const std::wstring &format, Args ... args)
{
	size_t size = _snwprintf(nullptr, 0, format.c_str(), args ...) + 1; // Extra space for '\0'

	if (size <= 0)
	{
		throw std::runtime_error("Error during formatting.");
	}

	std::unique_ptr<wchar_t[]> buf(new wchar_t[size]);
	_snwprintf(buf.get(), size, format.c_str(), args ...);
	return std::wstring(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
}

// получение строки из ресурсов. платформо- и системозависимая функция
std::wstring LoadStringFromResource(__in UINT stringID, __in_opt HINSTANCE instance = nullptr);


std::wstring CropStr(const std::wstring &str, const size_t len);

bool AnalyseImportFile(AnalyseFileStruct *a);
uint16_t CalcCRC(uint8_t *buffer, size_t len);

