using System; using System.Threading.Tasks; using System.IO; using Elwig.Helpers; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Linq; namespace Elwig.Documents { public abstract partial class Document : IDisposable { private TempFile? _pdfFile = null; private string? _renderedHtml = null; public bool ShowFoldMarks = App.Config.Debug; public string DataPath; public int CurrentNextSeason; public string? DocumentId; public string Title; public string Author; public string Header; public string Footer; public DateTime Date; public Document(string title) { var c = App.Client; DataPath = App.DataPath; CurrentNextSeason = Utils.CurrentNextSeason; Title = title; Author = c.NameFull; Header = $"<div class='name'>{c.Name}</div><div class='suffix'>{c.NameSuffix}</div><div class='type'>{c.NameTypeFull}</div>"; Footer = Utils.GenerateFooter("<br/>", " \u00b7 ") .Item(c.NameFull).NextLine() .Item(c.Address).Item($"{c.Plz} {c.Ort}").Item("Österreich").Item("Tel.", c.PhoneNr).Item("Fax", c.FaxNr).NextLine() .Item(c.EmailAddress).Item(c.Website).Item("Betriebs-Nr.", c.LfbisNr).Item("UID", c.UstIdNr).NextLine() .Item("BIC", c.Bic).Item("IBAN", c.Iban) .ToString(); Date = DateTime.Today; } [GeneratedRegex(@"</body>.*?</footer>\s*</div>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled)] private static partial Regex GeneratedDocumentHeaderRegex(); private static readonly Regex DocumentHeaderRegex = GeneratedDocumentHeaderRegex(); [GeneratedRegex(@"<style>.*?/style>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled)] private static partial Regex GeneratedHtmlStyleRegex(); private static readonly Regex HtmlStyleRegex = GeneratedHtmlStyleRegex(); [GeneratedRegex(@"<link[^>]*>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled)] private static partial Regex GeneratedHtmlLinkRegex(); private static readonly Regex HtmlLinkRegex = GeneratedHtmlLinkRegex(); ~Document() { Dispose(); } public void Dispose() { _pdfFile?.Dispose(); _pdfFile = null; GC.SuppressFinalize(this); } public static async Task<Document> Merge(IEnumerable<Document> docs) { string html = ""; var styles = new List<string>(); foreach (var d in docs) { var h = await d.Render(); var s = HtmlStyleRegex.Matches(h).Select(m => m.Value).ToList(); var l = HtmlLinkRegex.Matches(h).Select(m => m.Value).ToList(); if (s.All(styles.Contains)) { h = HtmlStyleRegex.Replace(h, ""); } else { styles.AddRange(s); } if (l.All(styles.Contains)) { h = HtmlLinkRegex.Replace(h, ""); } else { styles.AddRange(l); } html += h; } html = DocumentHeaderRegex.Replace(html, "<div class='document-break'/>"); return new InternalDocument("Mehrere Dokumente") { _renderedHtml = html, }; } private async Task<string> Render() { if (_renderedHtml != null) return _renderedHtml; string name; if (this is BusinessLetter) { name = "BusinessLetter"; } else if (this is DeliveryNote) { name = "DeliveryNote"; } else if (this is CreditNote) { name = "CreditNote"; } else if (this is DeliveryJournal) { name = "DeliveryJournal"; } else if (this is Letterhead) { name = "Letterhead"; } else if (this is DeliveryConfirmation) { name = "DeliveryConfirmation"; } else { throw new InvalidOperationException("Invalid document object"); } return await Render(name); } private async Task<string> Render(string name) { _renderedHtml = await Html.CompileRenderAsync(name, this); return _renderedHtml; } public async Task Generate() { var pdf = new TempFile("pdf"); using (var tmpHtml = new TempFile("html")) { await File.WriteAllTextAsync(tmpHtml.FilePath, await Render(), Utils.UTF8); await Pdf.Convert(tmpHtml.FilePath, pdf.FilePath); } _pdfFile = pdf; } public void SaveTo(string pdfPath) { if (_pdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet"); File.Copy(_pdfFile.FilePath, pdfPath); } public async Task Print(int copies = 1) { if (_pdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet"); await Pdf.Print(_pdfFile.FilePath, copies); } public void Show() { if (_pdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet"); Pdf.Show(_pdfFile.NewReference(), Title); } private class InternalDocument : Document { public InternalDocument(string title) : base(title) { } } } }