using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DeiNiu.wms.Logical
{
    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;
                    
                }
                else if (ptype == PrinterType.code)
                {
                    deviceInfo =
                                           "" +
                                         "  EMF" +
                                         "  10.0cm" +
                                         "  5.0cm" +
                                         "  0.0cm" +
                                         "  0.0cm" +
                                         "  0.0cm" +
                                         "  0.0cm" +
                                         "";
                    printerName = WmsConstants.PRINTER_NAME_CODE;
                 
                }
                else 
                {
                    deviceInfo =
                          "" +
                        "  EMF" +
                        "  21.0cm" +
                        "  29.7.0cm" +
                        "  0.5cm" +
                        "  0.5cm" +
                        "  0.5cm" +
                        "  0.5cm" +
                        "";
                    printerName = WmsConstants.PRINTER_NAME_A4;
                }
                Warning[] warnings;
                m_streams = new List();
               try{
                report.Render("Image", deviceInfo, CreateStream, out warnings);
               }catch(Exception e){
                   Console.WriteLine(e.InnerException.Message);
               }
                foreach (Stream stream in m_streams)
                    stream.Position = 0;
            }
            /// 
            /// 创建具有指定的名称和格式的流。
            /// 
            private Stream CreateStream(string name, string fileNameExtension,
          Encoding encoding, string mimeType, bool willSeek)
            {
                Stream stream = new FileStream(name + "." + 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;
                
                 ReportDataSource dataset = new ReportDataSource("DataSet1", dt);
                 report.DataSources.Add(dataset);
                 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;
            }
        }
        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;
            }
        }
    }