using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DeiNiu.wms.win.utils.print
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Drawing.Imaging;
    using System.Drawing.Printing;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Text;
    using Microsoft.Reporting.WinForms;
    using DeiNiu.Utils;
 
        /// 
        /// 通过RDLC向默认打印机输出打印报表
        /// 
        public class BillPrint : IDisposable
        {
            /// 
            /// 当前打印页号
            /// 
            static int m_currentPageIndex;
            /// 
            /// RDCL转换stream一页对应一个stream
            /// 
            static List m_streams;
            string printerName =  WmsConstants.PRINTER_NAME_A4;
            /// 
            /// 把report输出成stream
            /// 
            /// 传入需要Export的report
            private void Export(LocalReport report, PrinterType ptype)
            {
                string deviceInfo =
                  "" +
                  "  EMF" +
                    //"  2in" +
                    //"  20in" +
                    "  0in" +
                    "  0in" +
                    "  0in" +
                    "  0in" +
                  "";
             //   string deviceInfo = "";
                if (ptype ==  PrinterType.A4)
                {
                    deviceInfo =
                         "" +
                       "  EMF" +
                       "  21.0cm" +
                       "  29.7.0cm" +
                       "  0.5cm" +
                       "  0.5cm" +
                       "  0.5cm" +
                       "  0.5cm" +
                       "";
                    printerName = WmsConstants.PRINTER_NAME_A4;
                    if (String.IsNullOrEmpty(printerName))
                    {
                        string msg = String.Format("没有定义A4打印机,请先设置本地A4打印机");
                        throw new Exception(msg);
                    }
                }
                else if (ptype == PrinterType.code)
                {
                    deviceInfo =
                                           "" +
                                         "  EMF" +
                                         "  " +
                                         WmsConstants.PRINTER_CODE_WIDTH
                                         +
                                         "cm" +
                                         "  " +
                                         WmsConstants.PRINTER_CODE_HEIGHT
                                         +
                                         "cm" +
                                         "  0.0cm" +
                                         "  0.0cm" +
                                         "  0.0cm" +
                                         "  0.0cm" +
                                         "";
                    printerName = WmsConstants.PRINTER_NAME_CODE;
                    if (String.IsNullOrEmpty(printerName))
                    {
                        string msg = String.Format("没有定义条码打印机,请先设置本地条码打印机");
                        throw new Exception(msg);
                    }
                } 
                else if (ptype == PrinterType.pin)
                {
                    deviceInfo =
                         "" +
                       "  " +
                       WmsConstants.PRINTER_PIN_PAGE_FORMAT +
                       ""  +
                       
                        
                       "  "+
                          WmsConstants.PRINTER_PIN_PAGE_WIDTH+
                        "cm" +
                       "  "+
                          WmsConstants.PRINTER_PIN_PAGE_HEIGHT +
                        "cm" +
                      "  " +
                         WmsConstants.PRINTER_PIN_PAGE_MARGIN_TOP +
                      "cm" +
                       "  " +
                         WmsConstants.PRINTER_PIN_PAGE_MARGIN_LEFT + 
                       "cm" +
                       "  " +
                      WmsConstants.PRINTER_PIN_PAGE_MARGIN_RIGHT +
                       "cm" +
                       "  " +
                    WmsConstants.PRINTER_PIN_PAGE_MARGIN_BOTTOM +
                       "cm" +
                       
                       "";
                    printerName = WmsConstants.PRINTER_NAME_PIN;
                    if (String.IsNullOrEmpty(printerName))
                    {
                        string msg = String.Format("没有定义多联打印机,请先设置本地多联打印机");
                        throw new Exception(msg);
                    }
                
                } 
             
                Warning[] warnings;
                m_streams = new List();
               try{
                report.Render("Image", deviceInfo, CreateStream, out warnings);
               }catch(Exception e){
                   
                   Console.WriteLine(e.InnerException.Message);
                   throw (e);
               }
                foreach (Stream stream in m_streams)
                    stream.Position = 0;
            }
            /// 
            /// 创建具有指定的名称和格式的流。
            /// 
            private Stream CreateStream(string name, string fileNameExtension,
          Encoding encoding, string mimeType, bool willSeek)
            {
                Stream stream;
                try
                {
                      stream = new FileStream(name + "." + fileNameExtension,
                      FileMode.Create);
                }
                catch (Exception er)
                {
                     
                     stream = new FileStream(name+"_201" + "." + fileNameExtension,  FileMode.Create);
                }
                m_streams.Add(stream);
                return stream;
            }
            /// 
            /// 打印输出
            /// 
            private void PrintPage(object sender, PrintPageEventArgs ev)
            {
                Metafile pageImage =
                  new Metafile(m_streams[m_currentPageIndex]);
                ev.Graphics.DrawImage(pageImage, ev.PageBounds);
                m_currentPageIndex++;
                ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
            }
            /// 
            /// 打印预处理
            /// 
            private void Print()
            {
                PrintDocument printDoc = new PrintDocument();
                //string printerName = printDoc.PrinterSettings.PrinterName;
                if (m_streams == null || m_streams.Count == 0)
                    return;
                printDoc.PrinterSettings.PrinterName = printerName;
                if (!printDoc.PrinterSettings.IsValid)
                {
                    string msg = String.Format("找不到打印机 \"{0}\".", printerName);
                    throw new Exception(msg);
                }
                printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
                StandardPrintController spc = new StandardPrintController();
                printDoc.PrintController = spc;
                printDoc.Print();
            }
            public void Dispose()
            {
                if (m_streams != null)
                {
                    foreach (Stream stream in m_streams)
                        stream.Close();
                    m_streams = null;
                }
            }
            /// 
            /// 对外接口,启动打印
            /// 
            /// 打印报表对应的数据源
            /// 打印报表名称
            public static void Run(DataTable dt, String reportFile, PrinterType ptype, ReportParameter[] parameters = null)
            {
                 LocalReport report = new LocalReport();
               //  report.ReportEmbeddedResource = "DeiNiu.wms.Logical.reports." + reportFile;
               //  report.ReportEmbeddedResource =   reportFile;
                 report.ReportPath = getReportPath(reportFile);
                // report.ReportPath = "d:\\wmsReport\\" + reportFile;
                 ReportDataSource dataset = new ReportDataSource("DataSet1", dt);
                 ReportDataSource dataset2 = new ReportDataSource("DataSet2", dt);
                 report.DataSources.Add(dataset);
                 report.DataSources.Add(dataset2);
                 if (parameters != null)
                 {
                     report.SetParameters(parameters);
                 }
                m_currentPageIndex = 0;
                BillPrint billPrint = new BillPrint();
                billPrint.Export(report, ptype);
                billPrint.Print();
                billPrint.Dispose();
            }
            /// 
            /// 获取打印机状态
            /// 
            /// 打印机名称
            /// 输出打印机状态
            private static void GetPrinterStatus2(string printerName, ref uint status)
            {
                try
                {
                    string lcPrinterName = printerName;
                    IntPtr liHandle = IntPtr.Zero;
                    if (!Win32.OpenPrinter(lcPrinterName, out liHandle, IntPtr.Zero))
                    {
                        Console.WriteLine("print  is close");
                        return;
                    }
                    UInt32 level = 2;
                    UInt32 sizeNeeded = 0;
                    IntPtr buffer = IntPtr.Zero;
                    Win32.GetPrinter(liHandle, level, buffer, 0, out sizeNeeded);
                    buffer = Marshal.AllocHGlobal((int)sizeNeeded);
                    if (!Win32.GetPrinter(liHandle, level, buffer, sizeNeeded, out sizeNeeded))
                    {
                        Console.WriteLine(Environment.NewLine + "Fail GetPrinter:" + Marshal.GetLastWin32Error());
                        return;
                    }
                    Win32.PRINTER_INFO_2 info = (Win32.PRINTER_INFO_2)Marshal.PtrToStructure(buffer, typeof(Win32.PRINTER_INFO_2));
                    status = info.Status;
                    Marshal.FreeHGlobal(buffer);
                    Win32.ClosePrinter(liHandle);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            /// 
            /// 对外接口,调去打印机信息
            /// 
            /// 打印机名称
            /// 返回打印机当前状态
            public static string GetPrinterStatus(string printerName)
            {
                uint intValue = 0;
                PrintDocument pd = new PrintDocument();
                printerName = printerName == "" ? pd.PrinterSettings.PrinterName : printerName;
                GetPrinterStatus2(printerName, ref intValue);
                string strRet = string.Empty;
                switch (intValue)
                {
                    case 0:
                        strRet = "准备就绪(Ready)";
                        break;
                    case 4194432:
                        strRet = "被打开(Lid Open)";
                        break;
                    case 144:
                        strRet = "打印纸用完(Out of Paper)";
                        break;
                    case 4194448:
                        strRet = "被打开并且打印纸用完(Out of Paper && Lid Open)";
                        break;
                    case 1024:
                        strRet = "打印中(Printing)";
                        break;
                    case 32768:
                        strRet = "初始化(Initializing)";
                        break;
                    case 160:
                        strRet = "手工送纸(Manual Feed in Progress)";
                        break;
                    case 4096:
                        strRet = "脱机(Offline)";
                        break;
                    default:
                        strRet = "未知状态(unknown state)";
                        break;
                }
                return strRet;
            }
        static string getReportPath( string reportName)
        {
            string report = string.IsNullOrEmpty(WmsConstants.FILE_SVR_PRINT) ? "utils\\reports\\" : WmsConstants.FILE_SVR_PRINT + reportName;
            if (File.Exists(report ))
            {
                return report;
            }
            return "utils\\reports\\" + reportName;
        }
        }
        public class Win32
        {
            [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool OpenPrinter(string printer, out IntPtr handle, IntPtr printerDefaults);
            [DllImport("winspool.drv")]
            public static extern bool ClosePrinter(IntPtr handle);
            [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool GetPrinter(IntPtr handle, UInt32 level, IntPtr buffer, UInt32 size, out UInt32 sizeNeeded);
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            public struct PRINTER_INFO_2
            {
                public string pServerName;
                public string pPrinterName;
                public string pShareName;
                public string pPortName;
                public string pDriverName;
                public string pComment;
                public string pLocation;
                public IntPtr pDevMode;
                public string pSepFile;
                public string pPrintProcessor;
                public string pDatatype;
                public string pParameters;
                public IntPtr pSecurityDescriptor;
                public UInt32 Attributes;
                public UInt32 Priority;
                public UInt32 DefaultPriority;
                public UInt32 StartTime;
                public UInt32 UntilTime;
                public UInt32 Status;
                public UInt32 cJobs;
                public UInt32 AveragePPM;
            }
        }
       
    }