using Adaptation.Shared;
using Adaptation.Shared.Metrology;
using Adaptation.Shared.Properties;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.Json;

namespace Adaptation.FileHandlers.OpenInsightMetrologyViewer;

public class WSRequest
{
    public bool SentToMetrology { get; set; }
    public bool SentToSPC { get; set; }
    //

    public string Area { get; set; }
    public string Ccomp { get; set; }
    public string CellName { get; set; }
    public string CondType { get; set; }
    public string Date { get; set; }
    public string FlatZMean { get; set; }
    public string FlatZRadialGradient { get; set; }
    public string FlatZStdDev { get; set; }
    public string Folder { get; set; }
    public string GLimit { get; set; }
    public string GradeMean { get; set; }
    public string GradeRadialGradient { get; set; }
    public string GradeStdDev { get; set; }
    public int Id { get; set; }
    public string Layer { get; set; }
    public string Lot { get; set; }
    public string Model { get; set; }
    public string NAvgMean { get; set; }
    public string NAvgRadialGradient { get; set; }
    public string NAvgStdDev { get; set; }
    public string NslMean { get; set; }
    public string NslRadialGradient { get; set; }
    public string NslStdDev { get; set; }
    public string Operator { get; set; }
    public string PSN { get; set; }
    public string Pattern { get; set; }
    public string PhaseMean { get; set; }
    public string PhaseRadialGradient { get; set; }
    public string PhaseStdDev { get; set; }
    public string Plan { get; set; }
    public string RDS { get; set; }
    public string RampRate { get; set; }
    public string Reactor { get; set; }
    public string RhoAvgMean { get; set; }
    public string RhoAvgRadialGradient { get; set; }
    public string RhoAvgStdDev { get; set; }
    public string RhoMethod { get; set; }
    public string RhoslMean { get; set; }
    public string RhoslRadialGradient { get; set; }
    public string RhoslStdDev { get; set; }
    public string RsMean { get; set; }
    public string RsRadialGradient { get; set; }
    public string RsStdDev { get; set; }
    public string SetupFile { get; set; }
    public string StartVoltage { get; set; }
    public string StopVoltage { get; set; }
    public string UniqueId { get; set; }
    public string VdMean { get; set; }
    public string VdRadialGradient { get; set; }
    public string VdStdDev { get; set; }
    public string Wafer { get; set; }
    public string WaferSize { get; set; }
    public string Zone { get; set; }
    public List<pcl.Detail> Details { get; protected set; }
    public string ProcessDataStandardFormat { get; set; }

    [Obsolete("For json")] public WSRequest() { }

#pragma warning disable IDE0060
    internal WSRequest(IFileRead fileRead, Logistics logistics, List<pcl.Description> descriptions, string processDataStandardFormat = null)
#pragma warning restore IDE0060
    {
        ProcessDataStandardFormat = processDataStandardFormat;
        Id = -1;
        Details = new List<pcl.Detail>();
        CellName = logistics.MesEntity;
        pcl.Description x = descriptions[0];
        //Header
        {
            Area = x.Area;
            Ccomp = x.Ccomp;
            CondType = x.CondType;
            Date = x.Date;
            FlatZMean = x.FlatZMean;
            FlatZRadialGradient = x.FlatZRadialGradient;
            FlatZStdDev = x.FlatZStdDev;
            Folder = x.Folder;
            GLimit = x.GLimit;
            GradeMean = x.GradeMean;
            GradeRadialGradient = x.GradeRadialGradient;
            GradeStdDev = x.GradeStdDev;
            Operator = logistics.MesEntity;
            Layer = x.Layer;
            Lot = x.Lot;
            Model = x.Model;
            NAvgMean = x.NAvgMean;
            NAvgRadialGradient = x.NAvgRadialGradient;
            NAvgStdDev = x.NAvgStdDev;
            NslMean = x.NslMean;
            NslRadialGradient = x.NslRadialGradient;
            NslStdDev = x.NslStdDev;
            PSN = x.PSN;
            Pattern = x.Pattern;
            PhaseMean = x.PhaseMean;
            PhaseRadialGradient = x.PhaseRadialGradient;
            PhaseStdDev = x.PhaseStdDev;
            Plan = x.Plan;
            RDS = x.RDS;
            RampRate = x.RampRate;
            Reactor = x.Reactor;
            RhoAvgMean = x.RhoAvgMean;
            RhoAvgRadialGradient = x.RhoAvgRadialGradient;
            RhoAvgStdDev = x.RhoAvgStdDev;
            RhoMethod = x.RhoMethod;
            RhoslMean = x.RhoslMean;
            RhoslRadialGradient = x.RhoslRadialGradient;
            RhoslStdDev = x.RhoslStdDev;
            RsMean = x.RsMean;
            RsRadialGradient = x.RsRadialGradient;
            RsStdDev = x.RsStdDev;
            SetupFile = x.SetupFile;
            StartVoltage = x.StartVoltage;
            StopVoltage = x.StopVoltage;
            UniqueId = x.UniqueId;
            VdMean = x.VdMean;
            VdRadialGradient = x.VdRadialGradient;
            VdStdDev = x.VdStdDev;
            Wafer = x.Wafer;
            WaferSize = x.WaferSize;
            Zone = x.Zone;
        }
        pcl.Detail detail;
        foreach (pcl.Description description in descriptions)
        {
            detail = new pcl.Detail
            {
                FlatZ = description.FlatZ,
                Grade = description.Grade,
                HeaderUniqueId = description.HeaderUniqueId,
                NAvg = description.NAvg,
                Nsl = description.Nsl,
                Phase = description.Phase,
                RhoAvg = description.RhoAvg,
                Rhosl = description.Rhosl,
                UniqueId = description.UniqueId,
                Vd = description.Vd
            };
            Details.Add(detail);
        }
        Date ??= logistics.DateTimeFromSequence.ToString();
        if (UniqueId is null && Details.Any())
            UniqueId = Details[0].HeaderUniqueId;
    }

    /// <summary>
    /// Convert the raw data file to parsable file format - in this case from PCL to PDF
    /// </summary>
    /// <param name="sourceFile">source file to be converted to PDF</param>
    /// <returns></returns>
    private static string ConvertSourceFileToPdfWithChartData(string lincPDFCFileName, string sourceFile)
    {
        string result = Path.ChangeExtension(sourceFile, ".pdf");
        if (!File.Exists(result))
        {
            string arguments = string.Concat("-i \"", sourceFile, "\" -o \"", result, "\"");
            //string arguments = string.Concat("-dSAFER -dBATCH -dNOPAUSE -dFIXEDMEDIA -dFitPage -dAutoRotatePages=/All -dDEVICEWIDTHPOINTS=792 -dDEVICEHEIGHTPOINTS=612 -sOutputFile=\"", result, "\" -sDEVICE=pdfwrite \"", sourceFile, "\"");
            Process process = Process.Start(lincPDFCFileName, arguments);
            //Process process = Process.Start(ghostPCLFileName, arguments);
            _ = process.WaitForExit(30000);
            if (!File.Exists(result))
                throw new Exception("PDF file wasn't created");
        }
        return result;
    }

#pragma warning disable IDE0060
    internal static void PostOpenInsightMetrologyViewerAttachments(IFileRead fileRead, Logistics logistics, string openInsightMetrologyViewerAPI, string lincPDFCFileName, DateTime dateTime, string json, List<pcl.Description> descriptions, string matchDirectory)
#pragma warning restore IDE0060
    {
        if (string.IsNullOrEmpty(json))
        {
            WSRequest wsRequest = new(fileRead, logistics, descriptions, string.Empty);
            (json, WS.Results wsResults) = WS.SendData(openInsightMetrologyViewerAPI, wsRequest);
            if (!wsResults.Success)
                throw new Exception(wsResults.ToString());
        }
        WS.Results metrologyWSRequest = JsonSerializer.Deserialize<WS.Results>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
        long wsResultsHeaderID = metrologyWSRequest.HeaderID;
        string[] pclFiles = Directory.GetFiles(matchDirectory, "*.pcl", SearchOption.TopDirectoryOnly);
        if (pclFiles.Length != 1)
            throw new Exception($"Invalid source file count for <{wsResultsHeaderID}>!{Environment.NewLine}{json}");
        List<string> pdfFiles = new();
        pdfFiles.AddRange(Directory.GetFiles(matchDirectory, "*.pdf_old", SearchOption.TopDirectoryOnly));
        foreach (string pdfFile in pdfFiles)
            File.Delete(pdfFile);
        pdfFiles.Clear();
        pdfFiles.AddRange(Directory.GetFiles(matchDirectory, "*.pdf", SearchOption.TopDirectoryOnly));
        foreach (string pdfFile in pdfFiles)
            File.Move(pdfFile, Path.ChangeExtension(pdfFile, ".pdf_old"));
        pdfFiles.Clear();
        foreach (string pclFile in pclFiles.OrderBy(l => l))
            pdfFiles.Add(ConvertSourceFileToPdfWithChartData(lincPDFCFileName, pclFile));
        if (pdfFiles.Count == 0)
            throw new Exception("Invalid *.pdf file count!");
        List<WS.Attachment> headerAttachments = new()
        { new WS.Attachment(descriptions[0].HeaderUniqueId, "Data.pdf", pdfFiles[0]) };
        WS.AttachFiles(openInsightMetrologyViewerAPI, wsResultsHeaderID, headerAttachments, dataAttachments: null);
    }

}