using DigitalData.Core.Abstraction.Application.Repository; using EnvelopeGenerator.Application.Common.Configurations; using EnvelopeGenerator.Application.Exceptions; using EnvelopeGenerator.Application.Pdf.PSPDFKitModels; using EnvelopeGenerator.Domain.Constants; using EnvelopeGenerator.Domain.Entities; using GdPicture14; using MediatR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace EnvelopeGenerator.Application.Pdf; /// /// /// public class BurnPdfCommand : IRequest { } /// /// /// public class BurnPdfCommandHandler : IRequestHandler { /// /// /// private readonly PDFBurnerParams _pdfBurnerParams; private readonly AnnotationManager _manager; private readonly IRepository _signRepo; private readonly ILogger _logger; /// /// /// /// /// /// /// public BurnPdfCommandHandler(PDFBurnerParams pdfBurnerParams, AnnotationManager manager, IRepository signRepo, ILogger logger) { _pdfBurnerParams = pdfBurnerParams; _manager = manager; _signRepo = signRepo; _logger = logger; } /// /// /// /// /// /// /// public byte[] BurnAnnotsToPDF(byte[] pSourceBuffer, List pInstantJSONList, int envelopeId) { // read the elements of envelope with their annotations var elements = _signRepo .Where(sig => sig.Document.EnvelopeId == envelopeId) .Include(sig => sig.Annotations) .ToList(); return elements.Any() ? BurnElementAnnotsToPDF(pSourceBuffer, elements) : BurnInstantJSONAnnotsToPDF(pSourceBuffer, pInstantJSONList); } /// /// /// /// /// /// public byte[] BurnElementAnnotsToPDF(byte[] pSourceBuffer, List elements) { // Add background using var doc = PdfEditor.Pdf.FromMemory(pSourceBuffer); // TODO: take the length from the largest y pSourceBuffer = doc.Background(elements, 1.9500000000000002 * 0.93, 2.52 * 0.67) .ExportStream() .ToArray(); GdPictureStatus oResult; using var oSourceStream = new MemoryStream(pSourceBuffer); // Open PDF oResult = _manager.InitFromStream(oSourceStream); if (oResult != GdPictureStatus.OK) throw new BurnAnnotationException($"Could not open document for burning: [{oResult}]"); // Imported from background (add to configuration) var margin = 0.2; var inchFactor = 72; // Y offset of form fields var keys = new[] { "position", "city", "date" }; // add to configuration var unitYOffsets = 0.2; var yOffsetsOfFF = keys .Select((k, i) => new { Key = k, Value = unitYOffsets * i + 1 }) .ToDictionary(x => x.Key, x => x.Value); // Add annotations foreach (var element in elements) { var frameX = element.Left - 0.7 - margin; var frame = element.Annotations?.FirstOrDefault(a => a.Name == "frame"); var frameY = element.Top - 0.5 - margin; var frameYShift = (frame!.Y ?? default) - frameY * inchFactor; var frameXShift = (frame.X ?? default) - frameX * inchFactor; foreach (var annot in element.Annotations!) { if (!yOffsetsOfFF.TryGetValue(annot.Name, out var yOffsetofFF)) yOffsetofFF = 0; var y = frameY + yOffsetofFF; if (annot.Type == AnnotationType.PSPDFKit.FormField) { AddFormFieldValue( (annot.X ?? default) / inchFactor, y, (annot.Width ?? default) / inchFactor, (annot.Height ?? default) / inchFactor, element.Page, annot.Value ); } else if (annot.Type == AnnotationType.PSPDFKit.Image) { AddImageAnnotation( (annot.X ?? default) / inchFactor, annot.Name == "signature" ? ((annot.Y ?? default) - frameYShift) / inchFactor : y, (annot.Width ?? default) / inchFactor, (annot.Height ?? default) / inchFactor, element.Page, annot.Value ); } else if (annot.Type == AnnotationType.PSPDFKit.Ink) { AddInkAnnotation(element.Page, annot.Value); } } } // Save PDF using var oNewStream = new MemoryStream(); oResult = _manager.SaveDocumentToPDF(oNewStream); if (oResult != GdPictureStatus.OK) throw new BurnAnnotationException($"Could not save document to stream: [{oResult}]"); _manager.Close(); return oNewStream.ToArray(); } /// /// /// /// /// /// public byte[] BurnInstantJSONAnnotsToPDF(byte[] pSourceBuffer, List pInstantJSONList) { GdPictureStatus oResult; using var oSourceStream = new MemoryStream(pSourceBuffer); // Open PDF oResult = _manager.InitFromStream(oSourceStream); if (oResult != GdPictureStatus.OK) { throw new BurnAnnotationException($"Could not open document for burning: [{oResult}]"); } // Add annotation to PDF foreach (var oJSON in pInstantJSONList) { try { if (oJSON is string json) AddInstantJsonAnnotationToPdf(json); } catch (Exception ex) { _logger.LogWarning("Error in AddInstantJSONAnnotationToPDF - oJson: "); _logger.LogWarning(oJSON); throw new BurnAnnotationException("Adding Annotation failed", ex); } } oResult = _manager.BurnAnnotationsToPage(RemoveInitialAnnots: true, VectorMode: true); if (oResult != GdPictureStatus.OK) { throw new BurnAnnotationException($"Could not burn annotations to file: [{oResult}]"); } // Save PDF using var oNewStream = new MemoryStream(); oResult = _manager.SaveDocumentToPDF(oNewStream); if (oResult != GdPictureStatus.OK) { throw new BurnAnnotationException($"Could not save document to stream: [{oResult}]"); } _manager.Close(); return oNewStream.ToArray(); } private void AddInstantJsonAnnotationToPdf(string instantJson) { var annotationData = JsonConvert.DeserializeObject(instantJson); annotationData?.Annotations?.Reverse(); if (annotationData?.Annotations is null) return; foreach (var annotation in annotationData.Annotations) { _logger.LogDebug("Adding AnnotationID: {id}", annotation.Id); switch (annotation.Type) { case AnnotationType.PSPDFKit.Image: if (annotationData?.Attachments is not null) AddImageAnnotation(annotation, annotationData.Attachments); break; case AnnotationType.PSPDFKit.Ink: AddInkAnnotation(annotation); break; case AnnotationType.PSPDFKit.Widget: // Add form field values var formFieldValue = annotationData?.FormFieldValues? .FirstOrDefault(fv => fv.Name == annotation.Id); if (formFieldValue != null && !_pdfBurnerParams.IgnoredLabels.Contains(formFieldValue.Value)) { AddFormFieldValue(annotation, formFieldValue); } break; } } } private void AddFormFieldValue(double x, double y, double width, double height, int page, string value) { throw new NotImplementedException(); } private void AddFormFieldValue(Annotation pAnnotation, FormFieldValue formFieldValue) { throw new NotImplementedException(); } private void AddImageAnnotation(double x, double y, double width, double height, int page, string base64) { throw new NotImplementedException(); } private void AddImageAnnotation(Annotation pAnnotation, Dictionary pAttachments) { throw new NotImplementedException(); } private void AddInkAnnotation(int page, string value) { throw new NotImplementedException(); } private void AddInkAnnotation(Annotation pAnnotation) { throw new NotImplementedException(); } /// /// /// /// /// /// /// public Task Handle(BurnPdfCommand request, CancellationToken cancellationToken) { throw new NotImplementedException(); } }