using namespace std;

#include "stdafx.h"
#include <afxwin.h>
#include <afxext.h>
#include <afxdisp.h>
#include <afxdtctl.h>
#include <afxcmn.h>
#include <iostream>

#include "FontMaker_Cli.h"
#include "resource.h"

int CALLBACK EnumFontFamExProc(ENUMLOGFONTEX* lpelfe, NEWTEXTMETRICEX* lpntme, DWORD FontType, LPARAM lParam)
{return 100;}

BOOL is_fontface_exists() {
	CFont font;

	if (font.CreatePointFont(12, m_cmd_parser.fontface)) {
		LOGFONTW lf{};
		lf.lfCharSet = DEFAULT_CHARSET;
		wcscpy_s(lf.lfFaceName, min(LF_FACESIZE, m_cmd_parser.fontface.GetLength() + 1), m_cmd_parser.fontface.GetBuffer());
		int iRet = EnumFontFamiliesExW(GetWindowDC(GetConsoleWindow()), &lf, (FONTENUMPROC)EnumFontFamExProc, (LPARAM)0, 0);
		font.DeleteObject();
		return iRet == 100 ? TRUE : FALSE;
	}

	return FALSE;
}

void init_font()
{
	if (!is_fontface_exists()) {
		wcout << L"无法找到指定的字体文件:" << m_cmd_parser.fontface.GetString() << endl;
		exit(1);
	}

	ZeroMemory(&log_font, sizeof(log_font));
	lstrcpy(log_font.lfFaceName, m_cmd_parser.fontface);
	log_font.lfCharSet = DEFAULT_CHARSET;
	log_font.lfWeight = m_cmd_parser.font_weight;
	log_font.lfItalic = m_cmd_parser.font_itatlic;
	log_font.lfHeight = m_cmd_parser.font_size;

	if (m_hFont != NULL) {DeleteObject(m_hFont);}

	m_hFont = CreateFontIndirect(&log_font);
	m_bitfont.SetFont(m_hFont);
	m_bitfont.SetSize(m_cmd_parser.font_width, m_cmd_parser.font_height);
	m_bitfont.SetOffset(m_cmd_parser.font_offset_x, m_cmd_parser.font_offset_y);
}

BOOL set_charset(int resource_id)
{
	m_charset.Delete();

	HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(resource_id), L"CHARSET");
	if (!hRsrc) {return false;}

	HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
	if (!hGlobal) {return false;}

	LPVOID pResourceData = LockResource(hGlobal);
	if (!pResourceData) {return false;}

	DWORD dwSize = SizeofResource(NULL, hRsrc);
	if (0 == dwSize) {return false;}

	FreeResource(hGlobal);

	m_charset.CreateFromResource((LPCTSTR) pResourceData, dwSize);

	return true;
}

BOOL make_file(CString output_filename)
{
	CFile file;

	if (!file.Open(output_filename,
		CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone)) {
		wcout << L"创建目标文件 " << output_filename.GetString() << L" 失败!" << endl;
		exit(1);
	}

	// scan - 0: 水平, 1: 垂直
	//  msb - 1: 高位在前, 0: 低位在前
	//  var - 0: 固定宽带, 1: 可变宽度
	maker.MakeBinFile(&m_bitfont, &m_charset, &file, m_cmd_parser.scan_mode, m_cmd_parser.byte_order, m_cmd_parser.char_width);
	m_character_count += m_charset.GetCharCount();

	file.Close();

	wcout << L"保存文件 " << output_filename.GetString() << L" 成功" << endl;

	return true;
}

/*
*	合并的文件包括:
*		文件头 [24]:
*			[4] 文件标识符 - FMUX
*			[4] 文件大小
*			[1] 字体宽高
*			[2] 有效字符数量
*			[1] 是否包含 GB2312 索引表
*			[1] 扫描模式
*			[1] 字节顺序
*			[4] ASCII 字模起始地址
*			[4] GB2312 字模起始地址
*			[2] 保留字
*		GB2312 索引表
*		ASCII 字模数据
*		GB2312 字模数据
*/
BOOL combine_files() {
	CFile ascii_file, gb2312_file, combined_file;

	if (!ascii_file.Open(ascii_output_filename,
		CFile::modeRead | CFile::shareDenyNone)) {
		wcout << ascii_output_filename.GetString() << L" 文件不存在" << endl;
		exit(1);
	}

	if (!gb2312_file.Open(gb2312_output_filename,
		CFile::modeRead | CFile::shareDenyNone)) {
		wcout << gb2312_output_filename.GetString() << L" 文件不存在" << endl;
		exit(1);
	}

	HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(IDR_GB2312), L"CHARSET");
	if (!hRsrc) {return false;}

	HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
	if (!hGlobal) {return false;}

	LPVOID pResourceData = LockResource(hGlobal);
	if (!pResourceData) {return false;}

	DWORD dwSize = SizeofResource(NULL, hRsrc);
	if (0 == dwSize) {return false;}

	FreeResource(hGlobal);

	if (!combined_file.Open(m_cmd_parser.output_file,
		CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone)) {
		wcout << L"创建目标文件 " << m_cmd_parser.output_file.GetString() << L" 失败!" << endl;
		exit(1);
	}

	PFL_Header header = (PFL_Header)malloc(sizeof(FL_Header));

	header->magic[0] = 'F';
	header->magic[1] = 'M';
	header->magic[2] = 'U';
	header->magic[3] = 'X';

	DWORD length = FL_Header_Size + dwSize + (DWORD) ascii_file.GetLength() + (DWORD) gb2312_file.GetLength();
	header->file_size = length;
	header->font_height = m_cmd_parser.font_size;
	header->char_count = m_character_count;
	header->has_index_table = m_cmd_parser.has_index_table;
	header->scan_mode = m_cmd_parser.scan_mode;
	header->byte_order = m_cmd_parser.byte_order;

	if (m_cmd_parser.has_index_table) {
		header->ascii_start = FL_Header_Size + dwSize;
	} else {
		header->ascii_start = FL_Header_Size;
	}

	header->gb2312_start = header->ascii_start + (DWORD) ascii_file.GetLength();
	header->reserved[0] = '\0';
	header->reserved[1] = '\0';

	combined_file.Write(&header->magic, sizeof(header->magic));
	combined_file.Write(&header->file_size, sizeof(header->file_size));
	combined_file.Write(&header->font_height, sizeof(header->font_height));
	combined_file.Write(&header->char_count, sizeof(header->char_count));
	combined_file.Write(&header->has_index_table, sizeof(header->has_index_table));
	combined_file.Write(&header->scan_mode, sizeof(header->scan_mode));
	combined_file.Write(&header->byte_order, sizeof(header->byte_order));
	combined_file.Write(&header->ascii_start, sizeof(header->ascii_start));
	combined_file.Write(&header->gb2312_start, sizeof(header->gb2312_start));
	combined_file.Write(&header->reserved, sizeof(header->reserved));

	free(header);

	char* buffer;
	DWORD file_length;

	combined_file.Write(pResourceData, dwSize);

	file_length = (DWORD) ascii_file.GetLength();
	buffer = new char[file_length + 1];
	buffer[file_length] = 0;
	ascii_file.Read(buffer, file_length);

	combined_file.Write(buffer, file_length);

	file_length = (DWORD) gb2312_file.GetLength();
	buffer = new char[file_length + 1];
	buffer[file_length] = 0;
	gb2312_file.Read(buffer, file_length);

	combined_file.Write(buffer, file_length);

	ascii_file.Close();
	gb2312_file.Close();
	combined_file.Close();

	return true;
}

int main()
{
	wcout.imbue(locale("CHS"));

	BOOL output_file_generated = false;

	m_cmd_parser.parse();
	// m_cmd_parser.print_params();

	init_font();

	if (set_charset(IDR_ASCII)) {
		output_file_generated = make_file(ascii_output_filename);
	}

	if (set_charset(IDR_GB2312)) {
		output_file_generated &= make_file(gb2312_output_filename);
	}
	
	if (!output_file_generated) {
		wcout << L"创建字库文件失败" << endl;
		exit(1);
	}

	if (combine_files()) {
		wcout << L"创建字库文件 " << m_cmd_parser.output_file.GetString() << L" 成功" << endl;

		m_cmd_parser.print_params();
	}

	DeleteFile(ascii_output_filename);
	DeleteFile(gb2312_output_filename);

	system("pause");
	return 0;
}