using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.IO;

namespace CSRender
{
    class CompareTIFF
    {
        internal static int[] runPureVerify(string targetDir, string referenceDir,
            string shiftPixel, string colorMargin, string removePoint, string shadingOff, bool reportFlag,
            string reportName, string inDiffPath, string inTargetFileName, DateTime inDateTime, string inReportInfo, 
            string inAppDir, string inExePath, string inVerifyArg)
        {
            //実行用コンソールの呼び出し
            ProcessStartInfo processStartInfo = new ProcessStartInfo();
            processStartInfo.FileName = System.IO.Path.Combine(inExePath, "PureVerify.exe");
            processStartInfo.CreateNoWindow = true; // コマンドプロンプトを非表示
            processStartInfo.UseShellExecute = false; // シェル機能オフ

            //レポートに書き込む情報を編集
            inTargetFileName = System.IO.Path.GetFileNameWithoutExtension(inTargetFileName);
            string reportInfoPath = editEachReport(inAppDir,inTargetFileName, inReportInfo, targetDir, referenceDir);

            //引数設定
            processStartInfo.Arguments = inVerifyArg;

            //対象ファイル名を設定
            processStartInfo.Arguments += "/inspTiff \"";
            processStartInfo.Arguments += inTargetFileName + ".pdf";
            processStartInfo.Arguments += "\" ";

            //レポートファイル名を設定
            string timeForReport = "[" + inDateTime.ToString("yyMMdd_HHmm") + "]" + ".pdf";
            string TargetName = System.IO.Path.Combine(reportName, inTargetFileName + ".pdf" + timeForReport);
            processStartInfo.Arguments += "/inspReport \"";
            processStartInfo.Arguments += TargetName;
            processStartInfo.Arguments += "\" ";


            //Logファイル名を設定
            string logFileName = System.IO.Path.Combine(inAppDir, "PureVerify.Data", "RipVerify", "report", inTargetFileName + ".pdf.log");
            processStartInfo.Arguments += "/pureVLog \"";
            processStartInfo.Arguments += logFileName;
            processStartInfo.Arguments += "\" ";
            
            //差異画像の出力
            inDiffPath = System.IO.Path.Combine(inDiffPath, inTargetFileName);
            if (!Directory.Exists(inDiffPath))
            {
                Directory.CreateDirectory(inDiffPath);
            }
            processStartInfo.Arguments += "/outDiff \"";
            processStartInfo.Arguments += inDiffPath;
            processStartInfo.Arguments += "\" ";

            //レポート記述内容の参照先
            processStartInfo.Arguments += "/topPageInfo ";
            processStartInfo.Arguments += reportInfoPath;

            //コンソールへの出力を制御
            processStartInfo.Arguments += " /consoleOut ";
            processStartInfo.Arguments += "2";//0:新規のコンソールに出力、1:親コンソールに出力（無い場合は新規に）、2:NULLコンソールに出力

            //processStartInfo.Arguments += " > nul";

            Process process = Process.Start(processStartInfo);
            process.WaitForExit();
            process.Close();

            //process.WaitForExit();
            process.Close();

            //NGの数を取得
            int[] NGOfThisFile = getNgOfPDF(logFileName);

            //NGの含まれる場合レポート名の頭に【NG_】を付与
            NGReportName(TargetName, reportName);

            return NGOfThisFile.ToArray();
        }

        //固定の引数を事前に読み込み
        internal static string makeFixityArg(string targetDir, string referenceDir, string shiftPixel, 
            string colorMargin, string removePoint, string shadingOff, string inAppDir)
        {
            //指定ファイル
            string pureArguments = "/tar ";
            pureArguments += targetDir;

            //リファレンスファイル
            pureArguments += " /ref ";
            pureArguments += referenceDir;

            //EquiosCenterの場所
            string EquiosCenter = System.IO.Path.Combine(inAppDir, "PureVerify.Data", "EquiosCenter");
            pureArguments += " /equios ";
            pureArguments += EquiosCenter;

            //出力ファイル形式の引数
            pureArguments += " /work ";

            //processStartInfo.Arguments += workPath;
            string workDir = System.IO.Path.Combine(inAppDir, "PureVerify.Data", "RipVerify");
            pureArguments += workDir;

            //検版の指定（2だとNGログ検版（LOG-Diff）になる）
            pureArguments += " /operation \"1\"";
            //差異箇所マークのサイズを指定
            pureArguments += " /markdis \"50\"";
            //PDFReportの画像の圧縮形式（0:ZLIB、1:LZW、2:JPEG、3:JPEG2000、4:RUN_LENGTH）
            pureArguments += " /encode \"1\"";
            //検版結果OKとなったファイルリストをPDFレポートの最後に記載（0:記載しない、1:記載する）
            pureArguments += " /show \"1\"";
            //検版品質ファイルの選択（0:弱、1:中、2:強、3:カスタム）
            pureArguments += " /quality \"3\"";

            //検版パラメータの設定
            pureArguments += " /shiftpixel \"";
            pureArguments += shiftPixel;
            pureArguments += "\" /colormargin \"";
            pureArguments += colorMargin;
            pureArguments += "\" /removepoint \"";
            pureArguments += removePoint;
            pureArguments += "\" /shadingoff \"";
            pureArguments += shadingOff;
            pureArguments += "\" ";

            return pureArguments;
        }

        //指定先にレポートを移動
        internal static void moveReport(string resultPath, string workPath)
        {
            //string reportPath = System.IO.Path.Combine(resultPath, "report", "Log");
            string reportPath = System.IO.Path.Combine(resultPath, "Log");
            if (!Directory.Exists(reportPath))//指定先にreportフォルダがあるか
            {
                Directory.CreateDirectory(reportPath);//なければ新規でreportフォルダを作成
            }
            var PureReportPath = System.IO.Path.Combine(workPath, "report");
            var allReport = Directory.EnumerateFiles(PureReportPath
                , "*.pdf.log", SearchOption.TopDirectoryOnly);//reportフォルダ内の全てのファイルを取得
            foreach (string file in allReport)
            {
                string fileTarget = System.IO.Path.Combine(reportPath, System.IO.Path.GetFileName(file));//旧パスからファイル名を取得して新しいパスを作成
                File.Copy(file, fileTarget, true);//指定先にコピー
                File.Delete(file);//コピー元のファイルを削除
            }
            Directory.Delete(PureReportPath, true);
            Directory.CreateDirectory(PureReportPath);
        }

        //検版レポートのファイル名を取得
        internal static string getReportName(string workPath)
        {
            string[] reportFilePath = System.IO.Directory.GetFiles(System.IO.Path.Combine(workPath, "report")
                , "*.pdf", System.IO.SearchOption.TopDirectoryOnly);//レポートファイルのパスを取得
            string ReportName = System.IO.Path.GetFileName(reportFilePath[0]);//file名を抽出

            return ReportName;
        }

        //NGの含まれる検版レポート名を編集
        internal static void NGReportName(string inTargetName, string inReportPath)
        {
            //string searchName = "report_" + inTargetName;
            string searchfile = System.IO.Path.GetFileNameWithoutExtension(inTargetName) + "&*";
            var NGreportFileName = Directory.GetFiles(inReportPath, searchfile);
            var OKreportFileName = Directory.GetFiles(inReportPath, System.IO.Path.GetFileName(inTargetName));
            int NGCount = NGreportFileName.Length;
            if (NGCount > 0)
            {
                foreach (var oldPathName in NGreportFileName)
                {
                    string oldNGName = System.IO.Path.GetFileNameWithoutExtension(oldPathName);
                    oldNGName = oldNGName.Substring(0, oldNGName.Length - 4) + ".pdf";
                    string oldFile = System.IO.Path.GetFileName(oldPathName);
                    File.Copy(oldPathName, System.IO.Path.Combine(inReportPath, "NG_" + oldNGName), true);
                    File.Delete(oldPathName);
                }
            }
            else
            {
                foreach (var beforePathName in OKreportFileName)
                {
                    string oldFile = System.IO.Path.GetFileName(beforePathName);
                    File.Copy(beforePathName, System.IO.Path.Combine(inReportPath, "OK_" + oldFile), true);
                    File.Delete(beforePathName);
                }
            }
        }

        //NG画像の数を取得
        internal static int[] getNgOfPDF(string inLogPath)
        {
            string tranceNGString = File.ReadLines(inLogPath, Encoding.GetEncoding("Shift-JIS")).Skip(16).First();//17行目を抽出
            tranceNGString = tranceNGString.Replace("NG", "");//不要な部分をカット
            tranceNGString = tranceNGString.Replace("：", "");
            tranceNGString = tranceNGString.Replace(" ", "");

            string tranceAllString = File.ReadLines(inLogPath, Encoding.GetEncoding("Shift-JIS")).Skip(14).First();//15行目を抽出
            tranceAllString = tranceAllString.Replace("ALL", "");//不要な部分をカット
            tranceAllString = tranceAllString.Replace("：", "");
            tranceAllString = tranceAllString.Replace(" ", "");

            int NGDataNum = 0;
            int AllDataNum = 0;
            try
            {
                NGDataNum = Int32.Parse(tranceNGString);
                AllDataNum = Int32.Parse(tranceAllString);
            }
            catch (FormatException e)
            {
                NGDataNum = 0;
                AllDataNum = 0;
            }
            int[] DataNumSet = { NGDataNum, AllDataNum };

            return DataNumSet.ToArray();
        }

        //前回のログが内部に残っていれば削除（エラー防止）
        internal static void deleteOldLog(string inLogPath)
        {
            if (System.IO.Directory.EnumerateFileSystemEntries(inLogPath).Any())
            {
                DirectoryInfo logDirctory = new DirectoryInfo(inLogPath);
                FileInfo[] logFiles = logDirctory.GetFiles();
                foreach (FileInfo delFile in logFiles)
                {
                    delFile.Delete();
                }
            }
        }


        /// <summary>
        /// NGな画像の総数を取得
        /// </summary>
        internal static int getNGNum(string workDir)
        {
            int NGFileNum = 0;
            //logファイルを読み取り（NG数の記述されている行を抽出）
            string[] reportFiles = System.IO.Directory.GetFiles(workDir, "*.pdf.log", System.IO.SearchOption.TopDirectoryOnly);
            foreach (var logfileName in reportFiles)
            {

                int[] NumOfThisFile = CompareTIFF.getNgOfPDF(logfileName);
                int NumOfThisNG = NumOfThisFile[0];

                NGFileNum += NumOfThisNG;
            }

            return NGFileNum;
        }

        /// <summary>
        /// 指定ディレクトリ内のPDFファイル名を取得する
        /// </summary>
        internal static string[] getPDFName(string targetDir)
        {
            if (File.Exists(targetDir))//対象がファイルの場合
            {
                string[] targetFiles = { targetDir };
                return targetFiles;
            }
            else//対象がディレクトリの場合はGetFilesメソッドで読み取る
            {
                string[] targetFiles = System.IO.Directory.GetFiles(targetDir, "*.pdf", System.IO.SearchOption.TopDirectoryOnly);
                return targetFiles;
            }
        }


        /// <summary>
        /// 指定ディレクトリ内のPDFファイルのページ数を取得する
        /// </summary>
        internal static string getPDFPage(string[] targetFiles, string tiffDir)
        {
            int[] PDFPages = new int[targetFiles.Length];
            for (int i = 0; i < targetFiles.Length; i++)
            {
                string targetName = System.IO.Path.GetFileName(targetFiles[i]) + "*.tiff";
                string[] targetPDF = System.IO.Directory.GetFiles(tiffDir, targetName, System.IO.SearchOption.TopDirectoryOnly);
                PDFPages[i] = targetPDF.Length;
            }
            //文字列化
            string allPage = "";
            for (int i = 0; i < PDFPages.Length; i++)
            {
                if (i > 0)
                {
                    allPage += ",";
                }
                allPage += PDFPages[i];
            }
            return allPage;
        }

        /// <summary>
        /// 検版するPDFに応じたレポートの出力内容を編集する
        /// </summary>
        internal static string editEachReport(string inAppDir, string targetPDF, string textContent, string TarTiffPath, string RefTiffpath)
        {
            // .txtのパス
            string outInfoPath = System.IO.Path.Combine("PureVerify.Data", "RipVerify", "work", "OUT_INFO", "ReportInf");
            outInfoPath = System.IO.Path.Combine(inAppDir, outInfoPath);
            if (!Directory.Exists(outInfoPath))
            {
                Directory.CreateDirectory(outInfoPath);
            }
            //ユニークなファイル名(検版するファイル名)でテキストファイルを生成
            string replaceTarName = targetPDF.Replace(" ", "_");
            string reportInfoPath = System.IO.Path.Combine(outInfoPath, replaceTarName + "Inf.txt");
            //if (!File.Exists(reportInfoPath))
            //{
            //File.CreateText(reportInfoPath);
            //}
            //.txtファイルに記述する内容（ターゲットファイルとリファレンスファイル名）
            textContent += "**PDF_REF_NAME: \"" + targetPDF + ".pdf\"\r\n";
            textContent += "**PDF_TAR_NAME: \"" + targetPDF + ".pdf\"\r\n";

            //ページ数を取得
            string[] referenceTiff = System.IO.Directory.GetFiles(RefTiffpath, targetPDF + ".pdf*.tiff", System.IO.SearchOption.TopDirectoryOnly);
            string referenceAllPage = referenceTiff.Length.ToString();
            textContent += "**PDF_REF_PAGE_NUM: \"" + referenceAllPage + "\"\r\n";
            string[] targetTiff = System.IO.Directory.GetFiles(TarTiffPath, targetPDF + ".pdf*.tiff", System.IO.SearchOption.TopDirectoryOnly);
            string targetAllPage = targetTiff.Length.ToString();
            textContent += "**PDF_TAR_PAGE_NUM: \"" + targetAllPage + "\"\r\n";

            // StreamWriterオブジェクトのインスタンスを生成
            using (StreamWriter streamWriter = new StreamWriter(reportInfoPath, false, Encoding.GetEncoding("Shift_JIS")))
            {
                // Writeメソッドで文字列データを書き込む
                streamWriter.Write(textContent);
                // StreamWriterオブジェクトを閉じる
                streamWriter.Close();
            }

            return reportInfoPath;
        }

        /// <summary>
        /// 生成したレポート内容参照先txtファイルを全削除（次回に残さない）
        /// </summary>
        internal static void deleteReportTexts()
        {
            // .txtのパス
            string appPath = System.Reflection.Assembly.GetExecutingAssembly().Location;  //モジュールのパスを取得
            string appDirectory = appPath.Substring(0, appPath.LastIndexOf(@"\") + 1);    //モジュールの存在するディレクトリを取得
            string outInfoPath = System.IO.Path.Combine("PureVerify.Data", "RipVerify", "work", "OUT_INFO", "ReportInf");
            //ディレクトリ内のファイルを全て取得して全て削除
            DirectoryInfo reportTextDir = new DirectoryInfo(outInfoPath);
            FileInfo[] deleteTextFles = reportTextDir.GetFiles();
            foreach (FileInfo deleteTxt in deleteTextFles)
            {
                deleteTxt.Delete();
            }
        }

        /// <summary>
        /// レポートの出力内容を編集する
        /// </summary>
        internal static string getReportInfo(string allRipTime, string workBox, 
            string targetBoxText, string referenceBoxText, string ResolutionBoxText, string PageRangeText, string pageBoxText)
        {
            // exeのパス
            string appPath = System.Reflection.Assembly.GetExecutingAssembly().Location;  //モジュールのパスを取得
            //対象フォルダの内容
            string tarTiffDir = System.IO.Path.Combine(workBox, "work", "targetTIFF");
            //PDFの数
            string[] targetPDFs = CompareTIFF.getPDFName(targetBoxText);
            string targetNum = targetPDFs.Length.ToString();
            //PDFのページ数
            string targetAllPage = CompareTIFF.getPDFPage(targetPDFs, tarTiffDir);

            //リファレンスフォルダの内容
            string refTiffDir = System.IO.Path.Combine(workBox, "work", "referenceTIFF");
            //PDFの数
            string[] referencePDFs = CompareTIFF.getPDFName(referenceBoxText);
            string referenceNum = referencePDFs.Length.ToString();
            //PDFのページ数
            string referenceAllPage = CompareTIFF.getPDFPage(referencePDFs, refTiffDir);

            //.txtファイルに記述する内容
            string writeText = "**RESULT_RIP_TIME: \"" + allRipTime + "\"\r\n";
            writeText += "**ENV_VERSION: \"CSRender Ver 0.3.0\"\r\n";
            writeText += "**ENV_RIPVERIFY_PATH: \"" + appPath + "\"\r\n";
            writeText += "**ENV_RIP_PROCESSING: \"PDFium\"\r\n";
            writeText += "**ENV_IMAGE_RESO: \"" + ResolutionBoxText + "\"\r\n";
            if (PageRangeText == "指定")
            {
                writeText += "**ENV_INSPECTION_AREA_SPECIFY: \"" + pageBoxText + "\"\r\n";
            }
            else
            {
                writeText += "**ENV_INSPECTION_AREA_SPECIFY: \"ALL\"\r\n";
            }
            writeText += "**PDF_REF_FOLDER: \"" + referenceBoxText + "\"\r\n";
            writeText += "**PDF_REF_FILE_NUM: \"" + referenceNum + "\"\r\n";
            //writeText += "**PDF_REF_NAME: \"" + allReferenceName + "\"\r\n";
            //writeText += "**PDF_REF_PAGE_NUM: \"" + referenceAllPage + "\"\r\n";
            writeText += "**PDF_TAR_FOLDER: \"" + targetBoxText + "\"\r\n";
            writeText += "**PDF_TAR_FILE_NUM: \"" + targetNum + "\"\r\n";
            //writeText += "**PDF_TAR_NAME: \"" + allTargetName + "\"\r\n";
            //writeText += "**PDF_TAR_PAGE_NUM: \"" + targetAllPage + "\"\r\n";
            //string eachWriteTxet = writeText;

            return writeText;
        }

        /// <summary>
        /// 検版対象のPDFリストを作成する
        /// </summary>
        internal static string[] GetTargetList(string inTargetDir, string inRefarenceDir)
        {
            string[] targetPDFList = CompareTIFF.getPDFName(inTargetDir);
            string[] refPDFList = CompareTIFF.getPDFName(inRefarenceDir);
            List<string> InspectionPDFs = new List<string>(); ;
            int i = 0;
            foreach (var refPDF in refPDFList)
            {
                refPDFList[i] = System.IO.Path.GetFileName(refPDF);
                i++;
            }
            foreach (var tarPDF in targetPDFList)
            {
                if (refPDFList.Contains(System.IO.Path.GetFileName(tarPDF)))
                {
                    InspectionPDFs.Add(tarPDF);
                }

            }

            return InspectionPDFs.ToArray();
        }

        /// <summary>
        /// 対象となる画像数を取得する
        /// </summary>
        internal static int getNumOfTiff(string[] inPDFList, string iniffPath)
        {
            int NumOfTiff = 0;
            foreach (var tarPDF in inPDFList)
            {
                string tarFileName = System.IO.Path.GetFileName(tarPDF);
                string[] targetFiles = System.IO.Directory.GetFiles(iniffPath, tarFileName + "*.tiff", System.IO.SearchOption.TopDirectoryOnly);
                NumOfTiff += targetFiles.Length;
            }
            return NumOfTiff;
        }

        /// <summary>
        /// ダミーのPDFファイルを作成する
        /// </summary>
        internal static string createDummyFile(string inTargetPath, string inDummyDir, string inFileName)
        {
            string TargetDir = System.IO.Path.GetDirectoryName(inTargetPath);//ファイルパスを取得
            string TargetFile = System.IO.Path.GetFileName(inTargetPath);//ファイル名を取得
            if (inFileName == "")//名前が空ならパスから取得した名前を代入
            {
                inFileName = TargetFile;
            }
            File.Copy(inTargetPath, System.IO.Path.Combine(inDummyDir, inFileName), true);
            return inFileName;
        }

        /// <summary>
        /// ダミーのPDFファイルを削除する
        /// </summary>
        internal static void deleteDummyFile(string inDummyPath, string inDummyName)
        {
            File.Delete(System.IO.Path.Combine(inDummyPath, inDummyName));
        }

    }
}
