using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace RGD.Common
{
    public class RawPrinterHelper
    {
        // Structure and API declarions:
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public class DOCINFOA
        {
            [MarshalAs(UnmanagedType.LPStr)]
            public string pDocName;

            [MarshalAs(UnmanagedType.LPStr)]
            public string pOutputFile;

            [MarshalAs(UnmanagedType.LPStr)]
            public string pDataType;
        }

        [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);

        [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool ClosePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

        [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndDocPrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartPagePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndPagePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);

        // SendBytesToPrinter()
        // When the function is given a printer name and an unmanaged array
        // of bytes, the function sends those bytes to the print queue.
        // Returns true on success, false on failure.
        //发送字节到斑马打印机
        public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
        {
            Int32 dwError = 0, dwWritten = 0;
            IntPtr hPrinter = new IntPtr(0);
            DOCINFOA di = new DOCINFOA();
            bool bSuccess = false; // Assume failure unless you specifically succeed.

            di.pDocName = "My C#.NET RAW Document";
            di.pDataType = "RAW";

            // Open the printer.
            if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
            {
                // Start a document.
                if (StartDocPrinter(hPrinter, 1, di))
                {
                    // Start a page.
                    if (StartPagePrinter(hPrinter))
                    {
                        // Write your bytes.
                        bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                        EndPagePrinter(hPrinter);
                    }
                    EndDocPrinter(hPrinter);
                }
                ClosePrinter(hPrinter);
            }
            // If you did not succeed, GetLastError may give more information
            // about why not.
            if (bSuccess == false)
            {
                dwError = Marshal.GetLastWin32Error();
            }
            return bSuccess;
        }

        //发送prn文件到斑马打印机
        public static bool SendFileToPrinter(string szPrinterName, string szFileName)
        {
            // Open the file.
            FileStream fs = new FileStream(szFileName, FileMode.Open);
            // Create a BinaryReader on the file.
            BinaryReader br = new BinaryReader(fs);
            // Dim an array of bytes big enough to hold the file's contents.
            Byte[] bytes = new Byte[fs.Length];
            bool bSuccess = false;
            // Your unmanaged pointer.
            IntPtr pUnmanagedBytes = new IntPtr(0);
            int nLength;

            nLength = Convert.ToInt32(fs.Length);
            // Read the contents of the file into the array.
            bytes = br.ReadBytes(nLength);
            // Allocate some unmanaged memory for those bytes.
            pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
            // Copy the managed byte array into the unmanaged array.
            Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
            // Send the unmanaged bytes to the printer.
            bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
            // Free the unmanaged memory that you allocated earlier.
            Marshal.FreeCoTaskMem(pUnmanagedBytes);
            return bSuccess;
        }

        //发送条码编码到斑马打印机
        public static bool SendStringToPrinter(string szPrinterName, string szString)
        {
            IntPtr pBytes;
            Int32 dwCount;
            // How many characters are in the string?
            dwCount = szString.Length;
            // Assume that the printer is expecting ANSI text, and then convert
            // the string to ANSI text.
            pBytes = Marshal.StringToCoTaskMemAnsi(szString);
            // Send the converted ANSI string to the printer.
            SendBytesToPrinter(szPrinterName, pBytes, dwCount);
            Marshal.FreeCoTaskMem(pBytes);
            return true;
        }

        public static void startPrint()
        {
            //斑马打印机ZLP指令开始
            StringBuilder ZPL = new StringBuilder("");
            ZPL.Append("\r\n");
            //标题
            Font f0 = new Font("宋体", 50, FontStyle.Bold);
            Bitmap imgA = BarcodeUtils.CreateImage("安徽省供电公司计量中心", f0);
            ZPL.Append(BarcodeUtils.CreateBmpZLP(imgA, BarcodeUtils.ConvertImageToCode(imgA), "100"));
            //caption1
            Font f1 = new Font("宋体", 30, FontStyle.Bold);
            Bitmap img1 = BarcodeUtils.CreateImage("条 形 码：", f1);
            ZPL.Append(BarcodeUtils.CreateBmpZLP(img1, BarcodeUtils.ConvertImageToCode(img1), "101"));
            //caption2
            Font f2 = new Font("宋体", 30, FontStyle.Bold);
            Bitmap img2 = BarcodeUtils.CreateImage("分拣结论：", f2);
            ZPL.Append(BarcodeUtils.CreateBmpZLP(img2, BarcodeUtils.ConvertImageToCode(img2), "102"));
            //caption3
            Font f3 = new Font("宋体", 30, FontStyle.Bold);
            Bitmap img3 = BarcodeUtils.CreateImage("故障现象：", f3);
            ZPL.Append(BarcodeUtils.CreateBmpZLP(img3, BarcodeUtils.ConvertImageToCode(img3), "103"));

            //data1
            Font df1 = new Font("宋体", 30, FontStyle.Underline);
            Bitmap dimg1 = BarcodeUtils.CreateImage("barcode", df1);
            ZPL.Append(BarcodeUtils.CreateBmpZLP(dimg1, BarcodeUtils.ConvertImageToCode(dimg1), "201"));
            //data2
            Bitmap dimg2 = BarcodeUtils.CreateImage("sort_conclusion", df1);
            ZPL.Append(BarcodeUtils.CreateBmpZLP(dimg2, BarcodeUtils.ConvertImageToCode(dimg2), "202"));
            //data3

            List<int> imgIDS = new List<int>();

            //加入相关设置
            ZPL.Append("^XA");
            ZPL.Append("\r\n");
            ZPL.Append("^MMP");
            ZPL.Append("\r\n");
            ZPL.Append("^POI");
            ZPL.Append("\r\n");
            //开始打印文字
            //第一段
            ZPL.Append("^FT30,30^XG100.GRF,1,1^FS");
            ZPL.Append("\r\n");
            ZPL.Append("^FT30,140^XG101.GRF,1,1^FS");
            ZPL.Append("\r\n");
            ZPL.Append("^FT30,190^XG102.GRF,1,1^FS");
            ZPL.Append("\r\n");
            ZPL.Append("^FT30,240^XG103.GRF,1,1^FS");
            ZPL.Append("\r\n");
            ZPL.Append("^FT240,140^XG201.GRF,1,1^FS");
            ZPL.Append("\r\n");
            ZPL.Append("^FT240,190^XG202.GRF,1,1^FS");
            ZPL.Append("\r\n");

            //释放资源
            ZPL.Append("^PQ1,0,1,Y^XZ");
            ZPL.Append("\r\n");

            ZPL.Append("^XA^ID100.GRF^FS^XZ");
            ZPL.Append("\r\n");
            ZPL.Append("^XA^ID101.GRF^FS^XZ");
            ZPL.Append("\r\n");
            ZPL.Append("^XA^ID102.GRF^FS^XZ");
            ZPL.Append("\r\n");
            ZPL.Append("^XA^ID103.GRF^FS^XZ");
            ZPL.Append("\r\n");
            ZPL.Append("^XA^ID201.GRF^FS^XZ");
            ZPL.Append("\r\n");
            ZPL.Append("^XA^ID202.GRF^FS^XZ");
            ZPL.Append("\r\n");

            string printer = "ZDesigner ZE500R-4 RH-300dpi ZPL";
            bool isPrintOK = RawPrinterHelper.SendStringToPrinter(printer, ZPL.ToString());
        }

        public static bool print(string user_no, string user_add, string printer)
        {
            #region 绘制图片

            double dpmm = 12;
            int height = (int)(20 * dpmm);
            int width = (int)(35 * dpmm);

            Bitmap image = new Bitmap(width, height);

            Graphics g = Graphics.FromImage(image);
            g.Clear(Color.White);
            int y = 0;

            Font f0 = new Font("宋体", 24, FontStyle.Bold);
            Bitmap imgA = BarcodeUtils.CreateImage(user_no, f0);
            g.DrawImage(imgA, 0, 0);
            y = imgA.Height;

            Font f1 = new Font("宋体", 24, FontStyle.Bold);
            string ss = "";
            int sscount = 0;
            int rowcount = 0;
            for (int i = 0; i < user_add.Length; i++)
            {
                char c = user_add[i];
                byte[] bytes = System.Text.Encoding.Unicode.GetBytes(c.ToString());

                int H = Convert.ToInt32(bytes[1]);
                int L = Convert.ToInt32(bytes[0]);

                // 得到unicode编码
                int value = H * 256 + L;

                // 是全角
                if (value >= 12288 && value <= 65374)
                {
                    sscount = sscount + 2;
                    ss += c;
                }
                else
                {
                    sscount = sscount + 1;
                    ss += c;
                }

                if (sscount > 22 || (i + 1) == user_add.Length)
                {
                    Bitmap img = BarcodeUtils.CreateImage(ss, f1);
                    g.DrawImage(img, 0, y);
                    y += img.Height;
                    ss = "";
                    sscount = 0;
                    rowcount++;
                }
            }
            image.RotateFlip(RotateFlipType.Rotate270FlipNone);

            #endregion 绘制图片

            StringBuilder ZPL = new StringBuilder("");
            ZPL.Append("\r\n");

            ZPL.Append(BarcodeUtils.CreateBmpZLP(image, BarcodeUtils.ConvertImageToCode(image), "100"));

            //加入相关设置
            ZPL.Append("^XA");
            ZPL.Append("\r\n");
            ZPL.Append("^MMP");
            ZPL.Append("\r\n");
            //ZPL.Append("^POI");
            //ZPL.Append("\r\n");

            //开始打印
            ZPL.Append("^FO30,42^XG100.GRF,1,1^FS");
            ZPL.Append("\r\n");

            //释放资源
            ZPL.Append("^PQ1,0,1,Y^XZ");
            ZPL.Append("\r\n");

            ZPL.Append("^XA^ID100.GRF^FS^XZ");
            ZPL.Append("\r\n");

            image.Save(@"d:\a.bmp");
            StreamWriter sw = new StreamWriter(@"d:\a.txt", false);
            sw.Write(ZPL.ToString());
            sw.Close();
            ////斑马打印机ZLP指令开始
            //StringBuilder ZPL = new StringBuilder("");
            //ZPL.Append("\r\n");
            ////标题
            //Font f0 = new Font("宋体", 24, FontStyle.Bold);
            //Bitmap imgA = BarcodeUtils.CreateImage(user_no, f0);
            //ZPL.Append(BarcodeUtils.CreateBmpZLP(imgA, BarcodeUtils.ConvertImageToCode(imgA), "100"));

            //Font f1 = new Font("宋体", 24, FontStyle.Bold);
            //string ss = "";
            //int sscount = 0;
            //int rowcount = 0;
            //for (int i = 0; i < user_add.Length; i++)
            //{
            //    char c = user_add[i];
            //    byte[] bytes = System.Text.Encoding.Unicode.GetBytes(c.ToString());

            //    int H = Convert.ToInt32(bytes[1]);
            //    int L = Convert.ToInt32(bytes[0]);

            //    // 得到unicode编码
            //    int value = H * 256 + L;

            //    // 是全角
            //    if (value >= 12288 && value <= 65374)
            //    {
            //        sscount = sscount + 2;
            //        ss += c;
            //    }
            //    else
            //    {
            //        sscount = sscount + 1;
            //        ss += c;
            //    }

            //    if (sscount > 24 || (i + 1) == user_add.Length)
            //    {
            //        Bitmap img = BarcodeUtils.CreateImage(ss, f1);
            //        Graphics g
            //        ZPL.Append(BarcodeUtils.CreateBmpZLP(img, BarcodeUtils.ConvertImageToCode(img), "I" + rowcount));
            //        ss = "";
            //        sscount = 0;
            //        rowcount++;
            //    }
            //}

            ////加入相关设置
            //ZPL.Append("^XA");
            //ZPL.Append("\r\n");
            //ZPL.Append("^MMP");
            //ZPL.Append("\r\n");
            ////ZPL.Append("^POI");
            ////ZPL.Append("\r\n");

            ////开始打印文字
            ////第一段
            //ZPL.Append("^FT232,10^XG100.GRF,1,1^FS");
            //ZPL.Append("\r\n");

            //for (int i = 0; i < rowcount; i++)
            //{
            //    ZPL.Append("^FT" + (197 - 35 * i) + ",10^XGI" + i + ".GRF,1,1^FS");
            //    ZPL.Append("\r\n");
            //}

            ////释放资源
            //ZPL.Append("^PQ1,0,1,Y^XZ");
            //ZPL.Append("\r\n");

            //ZPL.Append("^XA^ID100.GRF^FS^XZ");
            //ZPL.Append("\r\n");

            //for (int i = 0; i < rowcount; i++)
            //{
            //    ZPL.Append("^XA^IDI" + i + ".GRF^FS^XZ");
            //    ZPL.Append("\r\n");
            //}
            //ZDesigner ZE500R-4 RH-300dpi ZPL
            bool isPrintOK = RawPrinterHelper.SendStringToPrinter(printer, ZPL.ToString());
            return isPrintOK;
        }
    }
}