using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Runtime.InteropServices;

namespace Project
{
    public partial class Form1 : Form
    {
        // Device communication API
        [DllImport("WoosimPrinter.DLL")]
        public static extern int ConnectSerialPrinter(string portName, int baudRate, int timeoutMsec, bool bProtocol);
        [DllImport("WoosimPrinter.DLL")]
        public static extern int ConnectUSBPrinter(int timeoutMsec, bool bProtocol);
        [DllImport("WoosimPrinter.DLL")]
        public static extern int ConnectWirelessPrinter(string IPAddress, int port, int timeoutMsec, bool bProtocol);
        [DllImport("WoosimPrinter.DLL")]
        public static extern bool ClosePrinterConnection();
        [DllImport("WoosimPrinter.DLL")]
        public static extern int PrintSpool(bool bDelete);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void EnterMSRMode(int n);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void CancelMSRMode();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void EnterSCRMode();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void CancelSCRMode();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void GetPrinterModelName();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void GetFirmwareVersion();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void GetPrinterStatus(int timeoutMsec);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void GetPrinterStatusEx(int timeoutMsec);

        // Printing data buffer handling
        [DllImport("WoosimPrinter.DLL")]
        public static extern void ClearSpool();
        [DllImport("WoosimPrinter.DLL")]
        public static extern int GetSpoolSize();
        [DllImport("WoosimPrinter.DLL")]
        public static extern IntPtr GetSpoolBuffer();

        // Append command & data to the printing data buffer
        [DllImport("WoosimPrinter.DLL")]
        public static extern int ControlCommand(byte[] data, int length);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void TextSaveSpool(string text);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void InitPrinterStatus();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void PrintData();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void PrintDotFeed(int dots);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void PrintLineFeed(int lines);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void SetCharCodeTable(int n, int mcu);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void SetFontSize(int n);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void SetTextAlignment(int n);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void SetTextStyle(int underline, bool bold, int width, int height, bool reverse);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void InitLineSpace();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void SetLineSpace(int n);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void SetAbsPosition(int distance);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void SetCharSpace(int n);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void SetUpsideDown(bool set);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void SetFontForTTF(string ttfFile);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void PrintSpoolForTTF(string data, int fontWidth, int fontHeight);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void SetPositionFromMark(int distance);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void FeedToMark();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void CutPaper(int mode);
        // Page mode
        [DllImport("WoosimPrinter.DLL")]
        public static extern void SetPageMode();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void InitPageMode(int x, int y, int width, int height);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_DrawLine(int x1, int y1, int x2, int y2, int thickness);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_DrawBox(int x, int y, int width, int height, int thickness);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_DrawEllipse(int x, int y, int radiusW, int radiusH, int thickness);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_DotFeed(int dots);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_LineFeed(int lines);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_Newline();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_ClearCurrentData();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_SetArea(int x, int y, int width, int height);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_SetDirection(int n);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_SetPosition(int x, int y);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_Print();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_SetStandardMode();
        [DllImport("WoosimPrinter.DLL")]
        public static extern void Page_Print_StandardMode();
        // Image
        [DllImport("WoosimPrinter.DLL")]
        public static extern void NormalBmpSaveSpool(string bmpFilePath);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void NormalAdjustBmpSaveSpool(string bmpFilePath, int contrast, int brightness);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void CompressedBmpSaveSpool(string bmpFilePath);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void CompressedAdjustBmpSaveSpool(string bmpFilePath, int contrast, int brightness);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void LoadLogoSaveSpool(int n);
        // Barcode 
        [DllImport("WoosimPrinter.DLL")]
        public static extern void OneDimensionBarcodeSaveSpool(int barcodeType, int width, int height, bool bHri, string barcodeData);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void PDF417SaveSpool(int width, int column, int level, int ratio, string barcodeData, bool bHri);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void DataMatrixSaveSpool(int width, int height, int module, string barcodeData);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void QRCodeSaveSpool(int version, char level, int module, string barcodeData);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void MicroPDF417SaveSpool(int width, int column, int row, int ratio, string barcodeData, bool bHri);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void TruncatedPDF417SaveSpool(int width, int column, int level, int ratio, string barcodeData, bool bHri);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void MaxicodeSaveSpool(int mode, string barcodeData);
        [DllImport("WoosimPrinter.DLL")]
        public static extern void GS1DatabarSaveSpool(int type, int n, string barcodeData);

        [DllImport("user32.dll")]
        public static extern uint RegisterWindowMessage(string message);


        private uint UWM_RECEIVE_DATA = RegisterWindowMessage("WOOSIM_PRT_OK");

        private const int DATA = 0x44;              // Response data from printer (ex. card data , model name, etc)
        private const int STATUS_ANSWER = 0x53;     // Response of printer status request

        // Common return value
        private const int SUCCESS = 1;
        private const int ALREADY_OPENED = -1;
        private const int TIMEOUT = -7;
        private const int NOT_OPEN_THE_PORT = -11;
        // Serial and Bluetooth connection error return value
        private const int UNABLE_TO_OPEN_THE_PORT = -2;
        private const int UNABLE_TO_CONFIGURE_THE_SERIAL_PORT = -3;
        private const int UNABLE_TO_SET_THE_TIMEOUT_PARAMETERS = -4;
        // Wireless network connection error return value
        private const int SOCKET_ERROR = -2;
        private const int CONNECT_FAIL = -3;
        // USB connection error return value
        private const int UNABLE_TO_MAKE_CONNECTION = -2;
        private const int UNABLE_TO_GET_INFOMATION = -3;
        private const int NOT_WOOSIM_PRINTER = -4;

        // Paper width with dot unit
        private const int _1INCH = 192;
        private const int _2INCH = 384;
        private const int _3INCH = 576;
        private const int _4INCH = 832;

        private enum Barcode : int { UPCA = 65, UPCE, EAN13, EAN8, CODE39, ITF, CODABAR, CODE93, CODE128 }
        private enum MCU : int { M16C, ARM, RX }

        private int connectionStatus;

        public Form1()
        {
            InitializeComponent();

            comboSerialPort.SelectedIndex = 0;  // COM1
            comboBaudrate.SelectedIndex = 3;    // 57600
            textBoxIP.Text = "192.168.10.1";
            textBoxIpPort.Text = "9100";
            comboMsr.SelectedIndex = 3;         // Triple Track

            connectionStatus = 0;
        }

        private void Form1Closing(object sender, FormClosingEventArgs e)
        {
            if (connectionStatus == SUCCESS)
                ClosePrinterConnection();
        }

        private void RadioSerial_CheckedChanged(object sender, EventArgs e)
        {
            if (radioSerial.Checked)
            {
                labelSerialPort.Show();
                labelBaudrate.Show();
                comboSerialPort.Show();
                comboBaudrate.Show();

                labelIP.Hide();
                labelIpPort.Hide();
                textBoxIP.Hide();
                textBoxIpPort.Hide();
            }
        }

        private void RadioUsb_CheckedChanged(object sender, EventArgs e)
        {
            if (radioUsb.Checked)
            {
                labelSerialPort.Hide();
                labelBaudrate.Hide();
                comboSerialPort.Hide();
                comboBaudrate.Hide();

                labelIP.Hide();
                labelIpPort.Hide();
                textBoxIP.Hide();
                textBoxIpPort.Hide();
            }
        }

        private void RadioTcpip_CheckedChanged(object sender, EventArgs e)
        {
            if (radioTcpip.Checked)
            {
                labelSerialPort.Hide();
                labelBaudrate.Hide();
                comboSerialPort.Hide();
                comboBaudrate.Hide();

                labelIP.Show();
                labelIpPort.Show();
                textBoxIP.Show();
                textBoxIpPort.Show();
            }
        }

        private void OpenButton_Click(object sender, EventArgs e)
        {
            if (connectionStatus == SUCCESS)
                return;

            if (radioSerial.Checked)
            {
                int baudrate = Int32.Parse(comboBaudrate.SelectedItem.ToString());
                connectionStatus = ConnectSerialPrinter(comboSerialPort.SelectedItem.ToString(), baudrate, 1000, false);
            }
            else if (radioUsb.Checked)
            {
                connectionStatus = ConnectUSBPrinter(1000, false);
            }
            else if (radioTcpip.Checked)
            {
                int port = Int32.Parse(textBoxIpPort.Text.ToString());
                connectionStatus = ConnectWirelessPrinter(textBoxIP.Text.ToString(), port, 5000, false);
            }

            if (connectionStatus == SUCCESS)
                labelComStatus.Text = "Connection success";
            else
                labelComStatus.Text = String.Format("Connection is failed with return value {0}", connectionStatus);
        }

        private void CloseButton_Click(object sender, EventArgs e)
        {
            if (connectionStatus == SUCCESS)
            {
                ClosePrinterConnection();
                connectionStatus = 0;
                labelComStatus.Text = "Connection closed";
            }
        }

        protected override void WndProc(ref Message msg)
        {
            if (msg.Msg == UWM_RECEIVE_DATA)
            {
                int type = msg.WParam.ToInt32() >> 16;
                int length = msg.WParam.ToInt32() & 0x0000FFFF;
                string strData = null;
                var byteArray = new byte[length];

                Marshal.Copy(msg.LParam, byteArray, 0, length);
                switch (type)
                {
                    case STATUS_ANSWER:
                        strData = String.Format("{0:X}", byteArray[0]);
                        break;

                    case DATA:
                        strData = String.Format("Receive {0} bytes\r\n\r\n", length);
                        strData += Encoding.Default.GetString(byteArray);
                        break;
                }
                textBoxRcvData.Text = strData;
            }
            base.WndProc(ref msg);
        }

        private void TextButton_Click(object sender, EventArgs e)
        {
            InitPrinterStatus();
            SetTextAlignment(1);
            TextSaveSpool("SALES  SLIP\n");
            SetTextAlignment(0);
            TextSaveSpool("--------------------------------\n");
            TextSaveSpool("MERCHANT NAME      Woosim Coffee\n");
            TextSaveSpool("MASTER                LEE IL BOK\n");
            TextSaveSpool("ADDRESS\n");
            TextSaveSpool("     #60, Sandan-ro 388beon-gil,\n");
            TextSaveSpool("    Galsan-myeon, Hongseong-gun,\n");
            TextSaveSpool("       Chungnam-do, 32200, Korea\n");
            TextSaveSpool("HELP DESK        +82-41-339-3700\n");
            TextSaveSpool("--------------------------------\n\n");
            TextSaveSpool("          WOOSIM  CARD          \n");
            TextSaveSpool("--------------------------------\n");
            TextSaveSpool("CARD NO.     4428-8819-0118-****\n");
            TextSaveSpool("EXPIRY                   2022/10\n");
            TextSaveSpool("--------------------------------\n");
            TextSaveSpool("TRANS. YEAR & DATE    2020/04/15\n");
            TextSaveSpool("TRANS CLASS             [Credit]\n");
            TextSaveSpool("TERMINAL ID.           123456789\n");
            TextSaveSpool("APPROVAL NO.           987654321\n");
            TextSaveSpool("AMOUNT                   500.00$\n");
            TextSaveSpool("--------------------------------\n");
            TextSaveSpool("SIGNATURE: \n\n");
            TextSaveSpool("--------------------------------\n\n");
            PrintSpool(true);
        }

        private void Barcode1button_Click(object sender, EventArgs e)
        {
            InitPrinterStatus();
            TextSaveSpool("UPCA\n");
            OneDimensionBarcodeSaveSpool((int)Barcode.UPCA, 2, 60, true, "012100000642");
            PrintData();
            TextSaveSpool("UPCE\n");
            OneDimensionBarcodeSaveSpool((int)Barcode.UPCE, 2, 60, true, "065100004328");
            PrintData();
            TextSaveSpool("EAN13\n");
            OneDimensionBarcodeSaveSpool((int)Barcode.EAN13, 2, 60, true, "123456478901");
            PrintData();
            TextSaveSpool("EAN8\n");
            OneDimensionBarcodeSaveSpool((int)Barcode.EAN8, 2, 60, true, "12345678");
            PrintData();
            TextSaveSpool("CODE39\n");
            OneDimensionBarcodeSaveSpool((int)Barcode.CODE39, 2, 60, true, "12345678901");
            PrintData();
            TextSaveSpool("ITF\n");
            OneDimensionBarcodeSaveSpool((int)Barcode.ITF, 2, 60, true, "123456");
            PrintData();
            TextSaveSpool("CODABAR\n");
            OneDimensionBarcodeSaveSpool((int)Barcode.CODABAR, 2, 60, true, "123456");
            PrintData();
            TextSaveSpool("CODE93\n");
            OneDimensionBarcodeSaveSpool((int)Barcode.CODE93, 2, 60, true, "12345678901");
            PrintData();
            TextSaveSpool("CODE128\n");
            OneDimensionBarcodeSaveSpool((int)Barcode.CODE128, 2, 60, true, "12345678901");
            PrintLineFeed(2);
            PrintSpool(true);
        }

        private void Barcode2Button_Click(object sender, EventArgs e)
        {
            InitPrinterStatus();
            TextSaveSpool("PDF417\n");
            PDF417SaveSpool(2, 2, 2, 4, "0123456789", false);
            PrintData();
            TextSaveSpool("DataMatrix\n");
            DataMatrixSaveSpool(36, 36, 2, "0123456789");
            PrintData();
            TextSaveSpool("QR Code\n");
            QRCodeSaveSpool(0, 'H', 3, "0123456789");
            PrintData();
            TextSaveSpool("Micro PDF417\n");
            MicroPDF417SaveSpool(2, 1, 0, 2, "01234567", false);
            PrintData();
            TextSaveSpool("Truncated PDF417\n");
            TruncatedPDF417SaveSpool(2, 2, 2, 2, "0123456789", false);
            PrintData();
            TextSaveSpool("Maxicode\n");
            MaxicodeSaveSpool(4, "0123456789");
            PrintData();
            PrintSpool(true);
        }

        private void TtfButton_Click(object sender, EventArgs e)
        {
            SetFontForTTF("WSTTFL.ttf");
            PrintSpoolForTTF("Woosim System Inc.", 30, 30);
            PrintLineFeed(2);
            PrintSpool(true);
        }

        private void PageSampleButton_Click(object sender, EventArgs e)
        {
            InitPageMode(0, 0, _2INCH, 700);
            SetTextStyle(0, true, 1, 1, false);
            TextSaveSpool("Woosim Cafe\n");

            SetTextStyle(0, false, 0, 0, false);
            TextSaveSpool("Coffee, tea and bread\n");
            PrintDotFeed(15);
            SetFontSize(1);
            Page_SetPosition(277, 105);
            TextSaveSpool("2020-01-27\n");
            SetFontSize(0);

            Page_SetPosition(290, 5);
            QRCodeSaveSpool(0, 'H', 2, "www.woosim.com/english");

            Page_DrawBox(0, 130, _2INCH, 0, 2);
            PrintDotFeed(5);
            TextSaveSpool(" #      Item      Num    Charge\n");
            TextSaveSpool(" 1      Latte      1     $ 3.35\n");
            TextSaveSpool(" 2  House Coffee   2     $ 3.98\n");
            TextSaveSpool(" 3       Tea       1     $ 1.95");
            PrintDotFeed(10);
            Page_DrawBox(0, 270, _2INCH, 0, 2);

            Page_DrawBox(0, 310, 115, 0, 2);
            Page_DrawBox(260, 310, 124, 0, 2);
            Page_SetPosition(123, 300);
            TextSaveSpool("Credit Card\n");
            TextSaveSpool("Number:         ");
            SetFontSize(1);
            TextSaveSpool("6688-9988-6644-3311\n");
            SetFontSize(0);
            TextSaveSpool("Payment:                $ 9.50\n");

            Page_DrawBox(0, 400, 120, 0, 2);
            Page_DrawBox(250, 400, 134, 0, 2);
            Page_SetPosition(145, 390);
            TextSaveSpool("Payment\n");
            TextSaveSpool("Price:                  $ 9.28\n");
            TextSaveSpool("Tax:                    $ 0.22\n");
            Page_DrawBox(0, 490, _2INCH, 0, 2);
            PrintDotFeed(15);
            TextSaveSpool("Total:                  $ 9.50\n");
            TextSaveSpool("Credit Card:            $ 9.50\n");

            Page_SetPosition(40, 580);
            OneDimensionBarcodeSaveSpool((int)Barcode.CODE128, 2, 50, true, "20150127123456789");
            PrintLineFeed(2);

            Page_Print_StandardMode();
            PrintSpool(true);
        }

        private void ImageButton_Click(object sender, EventArgs e)
        {
            string bmpPath = "./woosim.bmp";
            FileInfo fileInfo = new FileInfo(bmpPath);

            if (fileInfo.Exists == false)
            {
                MessageBox.Show("woosim.bmp file is not found!");
                return;
            }

            InitPrinterStatus();

            //Normal BMP file print
            TextSaveSpool("Print Bmp file \n");
            NormalBmpSaveSpool("./woosim.bmp");
            PrintLineFeed(2);

            //BMP file print using Compressed algorithm
            TextSaveSpool("Print Bmp file with compression\n");
            InitPageMode(0, 0, _2INCH, 200);
            CompressedBmpSaveSpool("./woosim.bmp");
            Page_Print_StandardMode();

            //Print image downloaded in printer
            TextSaveSpool("Print pre-downloaded image file #0\n");
            LoadLogoSaveSpool(0);
            PrintLineFeed(2);
            PrintSpool(true);
        }

        private void BoxLineButton_Click(object sender, EventArgs e)
        {
            //Initialization & make page
            InitPageMode(0, 0, _2INCH, _3INCH);

            //Draw Black & long box
            Page_DrawBox(_2INCH - 80, 30, 30, 150, 20);
            Page_DrawBox(_2INCH - 80, 200, 30, _3INCH - 200 - 30, 1);

            //Contained text "TEXT"
            Page_DrawBox(214, 224, 50, 258, 1);

            //Boxes in Box
            Page_DrawBox(60, 234, 104, 44, 1);
            Page_DrawBox(60, 312, 28, 150, 1);
            Page_DrawBox(98, 312, 28, 150, 1);
            Page_DrawBox(136, 312, 28, 150, 1);
            Page_DrawBox(50, 224, 124, 258, 3);

            //Draw vertical lines
            Page_DrawBox(205, 30, 0, 140, 1);
            Page_DrawBox(235, 30, 0, 140, 1);
            Page_DrawBox(265, 30, 0, 140, 1);

            //Draw horizontal lines
            Page_DrawBox(185, 55, 100, 0, 1);
            Page_DrawBox(185, 95, 100, 0, 1);
            Page_DrawBox(185, 135, 100, 0, 1);

            //Draw outline-Box
            Page_DrawBox(30, 0, _2INCH - 60, _3INCH, 1);

            Page_SetDirection(3);       // Clockwise rotation
            Page_SetPosition(214, 30);  // Y_pos, X_pos
            SetTextStyle(0, false, 1, 1, false);
            TextSaveSpool("Text");
            Page_SetPosition(270, 70);
            QRCodeSaveSpool(0, 'H', 2, "www.woosim.com/english");

            SetTextStyle(0, true, 1, 0, false);
            Page_SetPosition(126, 256); // Y_pos, X_pos
            TextSaveSpool("TEXT");
            Page_Print_StandardMode();

            Page_SetDirection(0);
            InitPageMode(0, 0, _2INCH, _2INCH);

            Page_DrawBox(0, 30, _2INCH, 0, 5);
            Page_DrawBox(30, 0, 0, _2INCH, 5);
            Page_DrawLine(30, 30, 170, 160, 3);
            Page_DrawLine(170, 160, 130, 190, 3);
            Page_DrawLine(130, 190, 210, 250, 3);
            Page_DrawLine(210, 250, 190, 270, 3);
            Page_DrawLine(190, 270, 270, 340, 3);
            Page_DrawLine(270, 340, 210, 370, 3);
            PrintData();
            Page_Print();

            Page_ClearCurrentData();
            Page_DrawBox(0, _1INCH, _2INCH, 0, 5);
            Page_DrawBox(_1INCH, 0, 0, _2INCH, 5);
            Page_DrawBox(_1INCH / 2, _1INCH, _1INCH, 0, 0);
            Page_DrawEllipse(_1INCH, _1INCH, _1INCH / 2, _1INCH - 20, 3);
            Page_Print_StandardMode();
            PrintLineFeed(2);

            PrintSpool(true);
        }

        private void StatusButton_Click(object sender, EventArgs e)
        {
            GetPrinterStatus(1000);
        }

        private void DevInfoButton_Click(object sender, EventArgs e)
        {
            GetPrinterModelName();
            GetFirmwareVersion();
        }

        private void SetMsrButton_Click(object sender, EventArgs e)
        {
            EnterMSRMode(comboMsr.SelectedIndex);
        }

        private void CancelMsrButton_Click(object sender, EventArgs e)
        {
            CancelMSRMode();
        }
    }
}
