using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing.Printing;
using System.Threading;

namespace Common.system
{
    /// <summary>
    /// 点阵文件制作打印
    /// 创建时间：2020年9月1日
    /// </summary>
    public class LatticeFileHelper
    {
        /// <summary>
        /// 打印进程
        /// </summary>
        public static Process PrintProcess = null;

        /// <summary>
        /// 输出日志文件地址  每个文件2MB左右
        /// </summary>
        private static string LogPath = "";
        /// <summary>
        /// 运行配置 首次打开必须运行
        /// </summary>
        public static void RunPrintConfig()
        {
            string Path = FileToolsCommon.GetFileAbsolutePath("/PrintTool/PrintConfig.exe");
            Process myProcess = new Process();
            LogPath = CreateLog();
            myProcess.StartInfo.FileName = Path;   //绝对路径
            //myProcess.StartInfo.Arguments = "";
            myProcess.StartInfo.UseShellExecute = false;           //不使用操作系统外壳程序启动
            myProcess.StartInfo.RedirectStandardError = true;      //重定向标准错误输出
            myProcess.StartInfo.CreateNoWindow = true;             //不显示程序窗口
            myProcess.StartInfo.RedirectStandardInput = true;      //用于模拟该进程控制台的输入
            //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
            myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
            myProcess.Start();                 //启动线程
            myProcess.BeginErrorReadLine();    //开始异步读取
            myProcess.WaitForExit();           //阻塞等待进程结束
            myProcess.Close();                 //关闭进程
            myProcess.Dispose();               //释放资源
        }

        /// <summary>
        /// 生成点阵打印文件
        /// </summary>
        /// <param name="PDFPath">PDF文件位置</param>
        /// <param name="SavePath">保存文件位置 TPF</param>
        /// <param name="PrintResult">输出结果，非0为失败</param>
        /// <param name="StandardError">错误信息</param>
        /// <param name="StandardOutput">输出信息["1536.688.35.70","1536.688.35.71","1536.688.35.72"]</param>
        /// <param name="PointType">0 为方点，1 为圆点 默认方点</param>
        public static void GeneratingPDF(string PDFPath, string SavePath, out int PrintResult, out string StandardError, out string StandardOutput, int PointType = 0)
        {
            //XML点阵文件位置
            string XmlFile = FileToolsCommon.GetFileAbsolutePath("/LatticeXML/print_license.xml");
            string ContentParameter = null;
            ContentParameter = "-sMode=Generate \"-sPDF=" + PDFPath + "\" \"-sLIC=" + XmlFile + "\" \"-oTPF=" + SavePath + "\" \"-dType=" + PointType + "\" ";//[-dType=0] [-dPrint=0] [-pStart=0]
            #region 制作点阵文件参数说明
            //-sMode = Generate - sPDF = d:\l\e.pdf - sLIC = d:\l\a.xml - oPDF = d:\l\11210.pdf"
            //当 - sMode = Generate，参数如下：
            //PrintTool.exe - sMode = Generate - sPDF = -sLIC = < -oPDF =| -oTPF=> [dType=] [-dPrint] [-pStart =]
            //- sPDF 原始 PDF 文件路径
            //- sLIC 点阵资源文件路径
            //- oPDF 生成的点阵 PDF 文件路径，-oPDF 与 - oTPF 至少设置一个。PDF 与 TPF 说明参见 2 生成文件类型说明
            //- oTPF 生成的 TPF 文件，-oPDF 与 - oTPF 至少设置一个。PDF 与 TPF 说明参见 2 生成文件类型说明 
            //- dType 0 为方点，1 为圆点；可选参数，默认 0。详细参数区别，参见 3.1 点阵形状
            //- dPrint 0 为激光打印机，1 为印刷机；可选参数，默认 0。详细参数区别，参见 3.2 点阵 PDF 适用打印场景
            //- pStart 整数，选择从哪页点阵资源开始制作点阵文件， 即起始点阵资源页序号；可选参数，默认0。关于 - pStart 的功能说明，参见 1.3.1.高级设置
            #endregion
            while (PrintProcess != null)
            {
                Thread.Sleep(100);
            }
            Process[] KillProcessArray = Process.GetProcessesByName("PrintTool");
            foreach (Process KillProcess in KillProcessArray)
            {
                KillProcess.Kill();
            }
            PrintProcess = new Process();
            LogPath = CreateLog();
            PrintProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath("/PrintTool/PrintTool.exe");   //绝对路径
            PrintProcess.StartInfo.Arguments = ContentParameter;
            PrintProcess.StartInfo.UseShellExecute = false;           //不使用操作系统外壳程序启动
            PrintProcess.StartInfo.RedirectStandardError = true;      //重定向标准错误输出
            PrintProcess.StartInfo.RedirectStandardOutput = true;
            PrintProcess.StartInfo.CreateNoWindow = true;             //不显示程序窗口
            PrintProcess.StartInfo.RedirectStandardInput = true;      //用于模拟该进程控制台的输入
            //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
            PrintProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
            PrintProcess.Start();                 //启动线程
            PrintProcess.WaitForExit();           //阻塞等待进程结束
            StandardError = PrintProcess.StandardError.ReadToEnd();
            StandardOutput = PrintProcess.StandardOutput.ReadToEnd();
            //PrintProcess.BeginErrorReadLine();    //开始异步读取
            Output("【制作点阵文件】错误：" + StandardError);
            Output("【制作点阵文件】返回信息：" + StandardOutput);
            PrintResult = PrintProcess.ExitCode;     //打印结果 非0则为打印失败
            Output("【制作点阵文件】" + ContentParameter);//记录打印日志
            PrintProcess.Close();                 //关闭进程
            PrintProcess.Dispose();               //释放资源
            #region 进程是否已经释放
            bool IsRunning = true;
            while (IsRunning)
            {
                IsRunning = false;
                Process[] ProcessArray = Process.GetProcessesByName("PrintTool");
                foreach (Process KillProcess in ProcessArray)
                {
                    IsRunning = true;
                    Thread.Sleep(100);
                }
            }
            #endregion
            PrintProcess = null;
        }

        /// <summary>
        /// 获取打印机列表
        /// </summary>
        /// <param name="DefaultPrinter">默认打印机</param>
        /// <returns>打印机列表</returns>
        public static List<string> GetPrinterList(out string DefaultPrinter)
        {
            List<string> PrintersList = new List<string>();
            DefaultPrinter = null;
            try
            {
                PrintDocument print = new PrintDocument();
                DefaultPrinter = print.PrinterSettings.PrinterName;//默认打印机名
                foreach (string sPrint in PrinterSettings.InstalledPrinters)//获取所有打印机名称
                {
                    PrintersList.Add(sPrint);
                }
            }
            catch (Exception)
            {

            }
            return PrintersList;
        }

        /// <summary>
        /// 打印TPF点阵文件
        /// </summary>
        /// <param name="TPFPath">TPF路径</param>
        /// <param name="PrinterNum">打印份数</param>
        /// <param name="PrinterName">打印机名称</param>
        /// <param name="PrintResult">输出结果，非0为失败</param>
        /// <param name="StandardError">错误信息</param>
        /// <param name="StandardOutput">输出信息</param>
        public static void PrinterTPFFile(string TPFPath, int PrinterNum, string PrinterName, out int PrintResult, out string StandardError, out string StandardOutput)
        {
            TPFPath = TPFPath.Replace("/", "\\");
            //XML点阵文件位置
            //string XmlFile = FileToolsCommon.GetFileAbsolutePath("/LatticeXML/print_license.xml");
            string ContentParameter = null;
            ContentParameter = " -sMode=Print \"-sTPF=" + TPFPath + "\" \"-sPrinter=" + PrinterName + "\" \"-dCopy=" + PrinterNum + "\"";//\"-dPaperSize=9\"
            #region 打印参数说明
            //-sMode = Print，参数如下：
            //PrintTool.exe - sMode = Print - sTPF = [-dCopy =][-dPaperSize =] - sPrinter =
            //-sTPF 需要打印的 TPF 文件路径
            //- dCopy 整数，可选参数，打印份数，默认 1 
            //- dPaperSize 整数，可选参数，设置打印纸张尺寸。不设置此值，系统自动选择匹配纸张打印；A4："-dPaperSize=9"  DMPAPER_A4	9	A4 210 x 297 mm   如
            //  需要手动设置纸张尺寸，不同尺寸纸张对应值，参见 https://docs.microsoft.com/en-us/windows/win32/intl/paper-sizes
            //- sPrinter 打印机名称
            // 打印完成后，如果打印成功，PrintTool.exe 退出值为 0。
            //如果打印失败，程序退出值为非 0。
            #endregion
            while (PrintProcess != null)
            {
                Thread.Sleep(100);
            }
            Process[] KillProcessArray = Process.GetProcessesByName("PrintTool");
            foreach (Process KillProcess in KillProcessArray)
            {
                KillProcess.Kill();
            }
            PrintProcess = new Process();
            LogPath = CreateLog();
            PrintProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath("/PrintTool/PrintTool.exe").Replace("/", "\\"); ;   //绝对路径
            PrintProcess.StartInfo.Arguments = ContentParameter;
            PrintProcess.StartInfo.UseShellExecute = false;           //不使用操作系统外壳程序启动
            PrintProcess.StartInfo.RedirectStandardError = true;      //重定向标准错误输出
            PrintProcess.StartInfo.RedirectStandardOutput = true;
            PrintProcess.StartInfo.CreateNoWindow = true;             //不显示程序窗口
            PrintProcess.StartInfo.RedirectStandardInput = true;      //用于模拟该进程控制台的输入
            //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
            PrintProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
            PrintProcess.Start();                 //启动线程
            //PrintProcess.BeginErrorReadLine();    //开始异步读取
            PrintProcess.WaitForExit();           //阻塞等待进程结束
            StandardError = PrintProcess.StandardError.ReadToEnd();
            StandardOutput = PrintProcess.StandardOutput.ReadToEnd();
            Output("【制作点阵文件】错误：" + StandardError);
            Output("【制作点阵文件】返回信息：" + StandardOutput);
            PrintResult = PrintProcess.ExitCode;     //打印结果 非0则为打印失败
            Output("【打印TPF文件】" + ContentParameter);//记录打印日志
            PrintProcess.Close();                 //关闭进程
            PrintProcess.Dispose();               //释放资源
            #region 进程是否已经释放
            bool IsRunning = true;
            while (IsRunning)
            {
                IsRunning = false;
                Process[] ProcessArray = Process.GetProcessesByName("PrintTool");
                foreach (Process KillProcess in ProcessArray)
                {
                    IsRunning = true;
                    Thread.Sleep(100);
                }
            }
            #endregion
            PrintProcess = null;
        }

        /// <summary>
        /// 创建日志文件
        /// </summary>
        /// <returns></returns>
        private static string CreateLog()
        {
            string LogFileName = DateTime.Now.ToString("yyyyMMdd");
            string LogFilePath = FileToolsCommon.GetFileAbsolutePath("/Log/PrintLog/");
            FileToolsCommon.CreateDirectory(LogFilePath);
            string LogName = LogFilePath + LogFileName + ".log";
            try
            {
                if (!FileToolsCommon.IsExistFile(LogName))
                {
                    FileToolsCommon.CreateFile(LogName);
                    //FileToolsCommon.AppendText(LogName, "\r\n****************************************************************************************************" +
                    //    "****************************************************************************************************\r\n");
                    return LogName;
                }
                else
                {
                    int num = 0;
                    while (FileToolsCommon.GetFileSizeByMB(LogName) > 2)
                    {
                        num++;
                        LogName = LogFilePath + LogFileName + "_" + num + ".log";
                        FileToolsCommon.CreateFile(LogName);
                    }
                    //FileToolsCommon.AppendText(LogName, "\r\n****************************************************************************************************" +
                    //    "****************************************************************************************************\r\n");
                    return LogName;
                }
            }
            catch (Exception)
            {
                return LogName;
            }
        }

        /// <summary>
        /// 输出日志
        /// </summary>
        /// <param name="Message"></param>
        private static void Output(string Message)
        {
            if (!string.IsNullOrEmpty(Message))
            {
                FileToolsCommon.AppendText(LogPath, Message + "\r\n");
                FileToolsCommon.AppendText(LogPath, "\r\n****************************************************************************************************" +
                         "****************************************************************************************************\r\n");
            }
        }
        /// <summary>
        /// 输出结果
        /// </summary>
        /// <param name="sendProcess"></param>
        /// <param name="output"></param>
        private static void Output(object sendProcess, DataReceivedEventArgs output)
        {
            Output(output.Data);
        }
    }
}
