//Reference: https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=72

#include "ESC_POS_Printer.h"

#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
#else
	#include <iostream>
#endif

//---------------------------------------------------------------------------
ESC_POS_Printer::ESC_POS_Printer()
{
	m_hPrinter = NULL;
	m_usb = false;
	m_Serial = NULL;
}
//---------------------------------------------------------------------------
ESC_POS_Printer::~ESC_POS_Printer()
{
	if (m_Serial != NULL)
	{
		close();
		delete m_Serial;
	}
}
//---------------------------------------------------------------------------
bool ESC_POS_Printer::openSerial(std::string ComNumber)
{
	m_Serial->Open(ComNumber);
	return true;
}
//---------------------------------------------------------------------------
bool ESC_POS_Printer::openUSB(std::wstring printerName)
{
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	bool result=true;
	if (!OpenPrinter((LPWSTR)printerName.c_str(), &m_hPrinter, NULL))
		result = false;
	m_usb = true;
	return result;
#else
	std::string str( printerName.begin(), printerName.end() );
	return openUSB(str);
#endif
}
//---------------------------------------------------------------------------
bool ESC_POS_Printer::openUSB(std::string printerName)
{
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	bool result=true;
	if (!OpenPrinter((LPWSTR)printerName.c_str(), &m_hPrinter, NULL))
		result = false;
	m_usb = true;
	return result;
#else
	m_hPrinter = fopen(printerName.c_str(), "w");
	if(m_hPrinter)
		return true;
	else
		return false;
#endif
}
//---------------------------------------------------------------------------
bool ESC_POS_Printer::Start()
{
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	DWORD Level = 1;
	std::wstring docName = L"Print ticket";

	DOC_INFO_1 pDocInfo;
	pDocInfo.pDocName = (LPWSTR)docName.c_str();
	pDocInfo.pOutputFile = NULL;
	pDocInfo.pDatatype = NULL;

	bool result = true;
	StartDocPrinter(m_hPrinter, Level, (BYTE*)&pDocInfo);
	if (!StartPagePrinter(m_hPrinter))
		result = false;
	return result;
#else
	return true;
#endif
}
//---------------------------------------------------------------------------
bool ESC_POS_Printer::End()
{
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	bool result = true;
	if (!EndPagePrinter(m_hPrinter))
		result = false;
	if (!EndDocPrinter(m_hPrinter))
		result = false;
	return result;
#else
	return true;
#endif
}
//---------------------------------------------------------------------------
bool ESC_POS_Printer::close()
{
	if (m_Serial != NULL)
	{
		m_Serial->Close();
	}
	if (m_hPrinter != NULL)
	{
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
		if (!EndPagePrinter(m_hPrinter))
			return false;
		if (!EndDocPrinter(m_hPrinter))
			return false;
		ClosePrinter(m_hPrinter);
#else
		if(fclose(m_hPrinter)==0)
			return true;
		else
			return false;
#endif
	}
	return true;
}
//---------------------------------------------------------------------------
//width - ������ � ������ (������ ���� ������ 8)
//height - ������ � ������
//bitArray - ������� ������
bool ESC_POS_Printer::printImage(int width, int height, unsigned char* bitArray)
{
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	DWORD Written = 0;
	int arLen = (width * height) / 8;

	char bCmdPrint[] = { 0x1d, 0x76, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 };
	int w = width;
	int h = height;
	bCmdPrint[4] = (((w / 8) >> 0) & 0xFF); //xL � xL and xH specify the horizontal direction data count for one bit image (xL + xH x 256) in bytes
	bCmdPrint[5] = (((w / 8) >> 8) & 0xFF); //xH
	bCmdPrint[6] = ((h >> 0) & 0xFF); //yL � yL and yH specify the vertical direction data count for one bit image (yL + yH x 256) in dots. 
	bCmdPrint[7] = ((h >> 8) & 0xFF); //yH
	WritePrinter(m_hPrinter, bCmdPrint, sizeof(bCmdPrint), &Written);
	WritePrinter(m_hPrinter, bitArray, arLen, &Written);

	return arLen == Written;
#else
	int Written = 0;
	int arLen = (width * height) / 8;

	char bCmdPrint[] = { 0x1d, 0x76, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 };
	int w = width;
	int h = height;
	bCmdPrint[4] = (((w / 8) >> 0) & 0xFF); //xL � xL and xH specify the horizontal direction data count for one bit image (xL + xH x 256) in bytes
	bCmdPrint[5] = (((w / 8) >> 8) & 0xFF); //xH
	bCmdPrint[6] = ((h >> 0) & 0xFF); //yL � yL and yH specify the vertical direction data count for one bit image (yL + yH x 256) in dots.
	bCmdPrint[7] = ((h >> 8) & 0xFF); //yH

	Written = fwrite(bCmdPrint, sizeof(char), sizeof(bCmdPrint), m_hPrinter);
	Written = fwrite(bitArray, sizeof(char), arLen, m_hPrinter);

	return arLen == Written;
#endif
}
//---------------------------------------------------------------------------
bool ESC_POS_Printer::Feed()
{
	char bCmdFeed[] = { 27, 100, 5 };

#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	DWORD Written = 0;
	WritePrinter(m_hPrinter, bCmdFeed, sizeof(bCmdFeed), &Written);
	return Written == 3;
#else
	int Written = 0;
	Written = fwrite(bCmdFeed, sizeof(char), sizeof(bCmdFeed), m_hPrinter);
	fflush(m_hPrinter);
	return Written == 3;
#endif
}
//---------------------------------------------------------------------------
bool ESC_POS_Printer::Cut()
{
	char bCmdCut[] = { 0x1B,0x6D };
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	DWORD Written = 0;
	WritePrinter(m_hPrinter, bCmdCut, sizeof(bCmdCut), &Written);
	return Written == 2;
#else
	int Written = 0;
	fwrite(bCmdCut, sizeof(char),sizeof(bCmdCut), m_hPrinter);
	fflush(m_hPrinter);
	return Written == 2;
#endif
}
//---------------------------------------------------------------------------
