using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace StdLabelPrint
{
	public partial class LabelPrint
	{
		public string printerName { get; set; } = string.Empty;
		public List<string> connectedPrinter = new List<string>();
		public string LastPrintZPL = string.Empty;
		public string qrData = string.Empty;
		public string baseZPL { get; set; }

		public LabelPrint(string _prtName)
		{
			//GetPrinterList();

			//if (connectedPrinter.Contains(_prtName) == false)
			//    throw new Exception("연결된 프린터가 아닙니다.");

			printerName = _prtName;
			baseZPL = Properties.Settings.Default.zpl;

		}

		public List<string> GetPrinterList()
		{
			connectedPrinter = new List<string>();
			var list_local = FindPrinters(PrinterEnumFlags.PRINTER_ENUM_LOCAL);
			var list_connected = FindPrinters(PrinterEnumFlags.PRINTER_ENUM_CONNECTIONS);
			try
			{
				connectedPrinter.AddRange(list_local);
			}
			catch { }

			try
			{
				connectedPrinter.AddRange(list_connected);
			}
			catch { }
			return connectedPrinter;
		}
		public string makeZPL_210101(Reel reel, Boolean D1RID, Boolean drawbox, out string qrData)
		{
			string prtData = string.Empty;
			qrData = string.Format("{0};{1};{2};{3};{4};{5};{6}", reel.sid, reel.lot, reel.manu, reel.qty, reel.id, reel.mfg, reel.partnum);
			prtData = "^XA\r\n";
			prtData += "^MMT\r\n";
			prtData += "^PW519\r\n";
			prtData += "^LL0200\r\n";
			prtData += "^LS0\r\n";
			prtData += "^FO128,96^GFA,01536,01536,00048,:Z64:\r\n";
			prtData += "eJxjYBgFo2AUkADs/xMN/g1G9aNgFMABAIF9rE0=:1194\r\n";

			if (drawbox)
				prtData += "^FO1,7^GB505,185,4^FS\r\n";

			prtData += "^BY2,3,41^FT280,82^BCN,,N,N,N,A\r\n";
			prtData += "^FD" + reel.sid + "^FS\r\n";
			prtData += "^FT12,160^BQN,2,4\r\n";
			prtData += string.Format("^FH\\^FDLA,{0}^FS\r\n", qrData);
			prtData += "^BY2,3,32^FT86,185^BCN,,N,N,N,A\r\n";
			prtData += string.Format("^FD{0};{1}^FS\r\n", reel.sid, reel.lot);
			prtData += "^FO278,7^GB0,26,4^FS\r\n";
			prtData += "^FT160,29^A0N,20,19^FH\\^FDSID^FS\r\n";
			prtData += "^FT159,111^A0N,20,19^FH\\^FDPN^FS\r\n";
			prtData += "^FT159,137^A0N,20,19^FH\\^FDRID^FS\r\n";
			prtData += "^FT194,29^A0N,20,19^FH\\^FD" + reel.sid + "^FS\r\n";
			prtData += "^FT324,29^A0N,20,19^FH\\^FD" + reel.lot + "^FS\r\n";
			prtData += "^FT195,111^A0N,20,19^FH\\^FD" + reel.partnum + "^FS\r\n";

			prtData += "^FT195,137^A0N,20,19^FH\\^FD" + (D1RID ? reel.id : string.Empty) + "^FS\r\n";   //210302

			prtData += "^FT441,137^A0N,20,19^FH\\^FD" + reel.qty.ToString() + "^FS\r\n";
			prtData += "^FT285,29^A0N,20,19^FH\\^FDLOT^FS\r\n";
			prtData += "^FT396,137^A0N,20,19^FH\\^FDQTY^FS\r\n";
			prtData += "^FO154,7^GB352,28,4^FS\r\n";
			prtData += "^FO154,89^GB352,54,4^FS\r\n";
			prtData += "^FO190,90^GB0,51,4^FS\r\n";
			prtData += "^FO188,9^GB0,24,4^FS\r\n";
			prtData += "^FO388,117^GB0,26,4^FS\r\n";
			prtData += "^FO430,116^GB0,26,4^FS\r\n";
			prtData += "^FO316,7^GB0,26,4^FS\r\n";
			prtData += "^PQ1,0,1,Y^XZ\r\n";
			return prtData;
		}
		public string makeZPL_210510(Reel reel, Boolean drawbox, out string qrData)
		{
			string m_strSend = string.Empty;
			qrData = string.Format("{0};{1};{2};{3};{4};{5}", reel.sid, reel.lot, reel.partnum, reel.qty, reel.id, reel.mfg);

			m_strSend = this.baseZPL;
			m_strSend = m_strSend.Replace("{qrData}", qrData);
			m_strSend = m_strSend.Replace("{sid}", reel.sid);
			m_strSend = m_strSend.Replace("{lot}", reel.lot);
			m_strSend = m_strSend.Replace("{partnum}", reel.partnum);
			m_strSend = m_strSend.Replace("{rid}", reel.id);
			m_strSend = m_strSend.Replace("{qty}", reel.qty.ToString());
			m_strSend = m_strSend.Replace("{mfg}", reel.mfg);
			m_strSend = m_strSend.Replace("{supply}", reel.manu);

			//줄바꿈제거
			m_strSend = m_strSend.Replace("\r", "").Replace("\n", "");
			return m_strSend;
		}
		public string makeZPL_210908(Reel reel, Boolean drawbox, out string qrData)
		{
			string m_strSend = string.Empty;
			qrData = string.Format("{0};{1};{2};{3};{4};{5};{6}", reel.sid, reel.lot, reel.manu, reel.qty, reel.id, reel.mfg, reel.partnum);

			m_strSend = this.baseZPL;
			m_strSend = m_strSend.Replace("{qrData}", qrData);
			m_strSend = m_strSend.Replace("{sid}", reel.sid);
			m_strSend = m_strSend.Replace("{lot}", reel.lot);
			m_strSend = m_strSend.Replace("{partnum}", reel.partnum);
			m_strSend = m_strSend.Replace("{rid}", reel.id);
			m_strSend = m_strSend.Replace("{qty}", reel.qty.ToString());
			m_strSend = m_strSend.Replace("{mfg}", reel.mfg);
			m_strSend = m_strSend.Replace("{supply}", reel.manu);

			//줄바꿈제거
			m_strSend = m_strSend.Replace("\r", "").Replace("\n", "");
			return m_strSend;
		}
		public Boolean TestPrint(Boolean drawbox, string manu = "", string mfgdate = "", Boolean Array7 = false)
		{
			var dtstr = DateTime.Now.ToShortDateString();
			var printcode = "103077807;Z577603504;105-35282-1105;15000;RC00004A219001W;20210612";
			var reel = new StdLabelPrint.Reel(printcode);
			//reel.id = "RLID" + DateTime.Now.ToString("MMHHmmssfff");
			reel.sid = "103000000";
			reel.partnum = "PARTNO".PadRight(20, '0'); //20자리

			if (mfgdate == "") reel.mfg = dtstr;
			else reel.mfg = mfgdate;

			reel.lot = "LOT000000000";
			if (manu == "") reel.manu = "ATK4EET1";
			else reel.manu = manu;

			reel.qty = 15000;
			var rlt = Print(reel, true, drawbox, Array7);
			var fi = new System.IO.FileInfo(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "temp_zpl.txt"));
			System.IO.File.WriteAllText(fi.FullName, LastPrintZPL, System.Text.Encoding.Default);
			return rlt;
		}


		public Boolean Print(Reel reel, Boolean display1drid, Boolean drawOUtBox, Boolean Array7 = false)
		{
			string prtData;
			if (Array7)
				prtData = makeZPL_210908(reel, drawOUtBox, out qrData);
			else
				prtData = makeZPL_210510(reel, drawOUtBox, out qrData);

			return Print(prtData);
		}

		public bool Print(string _zpl)
		{
			this.LastPrintZPL = _zpl;

			bool retval = false;
			System.IntPtr lhPrinter = new System.IntPtr();
			DOCINFO di = new DOCINFO();
			int pcWritten = 0;
			//string st1;
			// text to print with a form feed character
			//st1 = "This is std label by using zpl\f";
			di.pDocName = "Component Std Label";
			di.pDataType = "RAW";
			// the \x1b means an ascii escape character

			//lhPrinter contains the handle for the printer opened
			//If lhPrinter is 0 then an error has occured

			//GetPrinterList();

			//if (connectedPrinter.Contains(printerName) == false)
			//    throw new Exception("연결된 프린터가 아닙니다.");


			PrintDirect.OpenPrinter(printerName, ref lhPrinter, 0);
			PrintDirect.StartDocPrinter(lhPrinter, 1, ref di);
			PrintDirect.StartPagePrinter(lhPrinter);
			try
			{
				PrintDirect.WritePrinter(lhPrinter, _zpl, _zpl.Length, ref pcWritten);
				retval = true;
			}
			catch (Exception e)
			{
				Console.WriteLine(e.Message);
			}
			PrintDirect.EndPagePrinter(lhPrinter);
			PrintDirect.EndDocPrinter(lhPrinter);
			PrintDirect.ClosePrinter(lhPrinter);
			return retval;
		}
		private List<string> FindPrinters(PrinterEnumFlags Flags)
		{
			List<string> prtList = new List<string>();
			uint cbNeeded = 0;
			uint cReturned = 0;
			if (PrintDirect.EnumPrinters(Flags, null, 2, IntPtr.Zero, 0, ref cbNeeded, ref cReturned))
			{
				return null;
			}
			int lastWin32Error = Marshal.GetLastWin32Error();
			if (lastWin32Error == ERROR_INSUFFICIENT_BUFFER)
			{
				IntPtr pAddr = Marshal.AllocHGlobal((int)cbNeeded);
				if (PrintDirect.EnumPrinters(Flags, null, 2, pAddr, cbNeeded, ref cbNeeded, ref cReturned))
				{
					PRINTER_INFO_2[] printerInfo2 = new PRINTER_INFO_2[cReturned];
					int offset = pAddr.ToInt32();
					Type type = typeof(PRINTER_INFO_2);
					int increment = Marshal.SizeOf(type);
					for (int i = 0; i < cReturned; i++)
					{
						printerInfo2[i] = (PRINTER_INFO_2)Marshal.PtrToStructure(new IntPtr(offset), type);
						prtList.Add(printerInfo2[i].pPrinterName);
						offset += increment;
					}
					Marshal.FreeHGlobal(pAddr);
					return prtList;
				}
				lastWin32Error = Marshal.GetLastWin32Error();
			}
			throw new Win32Exception(lastWin32Error);
		}



	}
	public class Reel
	{
		public string sid { get; set; }
		public string lot { get; set; }
		public string mfg { get; set; }
		public int qty { get; set; }
		public string id { get; set; }
		//public string date { get; set; }
		public string partnum { get; set; }
		public string manu { get; set; }

		public Reel()
		{
			Clear();
		}
		public void Clear()
		{
			sid = string.Empty;
			lot = string.Empty;
			mfg = string.Empty;
			lot = string.Empty;
			id = string.Empty;
			//date = string.Empty;
			partnum = string.Empty;
			manu = string.Empty;
			qty = 0;
		}
		public Reel(string _sid, string _lot, string _manu, int _qty, string _id, string _mfgdate, string _partnum)
		{
			int sidNum = 0;
			if (int.TryParse(_sid, out sidNum) && sidNum.ToString().Length == 9)
				sid = sidNum.ToString();
			else
				throw new Exception("SID가 숫자가 아니거나 9자리 숫자가 아닙니다.");

			lot = _lot;
			mfg = _mfgdate;
			qty = _qty;
			id = _id;
			partnum = _partnum;
			manu = _manu;
		}
		public Reel(string qrbarcodestr)
		{
			var spData = qrbarcodestr.Split(';');
			if (spData.Length < 6)
				throw new Exception("Barcode Length가 적습니다.");

			sid = spData[0];
			lot = spData[1];
			manu = spData[2];

			int _qty = 0;

			if (int.TryParse(spData[3], out _qty))
				qty = _qty;
			else
				throw new Exception("수량란에 숫자 정보가 아닙니다.");

			id = spData[4];
			mfg = spData[5];
			if (spData.Length > 6) partnum = spData[6];
			else partnum = string.Empty;
		}
	}
}
