using Elwig.Models.Entities; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Elwig.Helpers.Export { public class VCard : IExporter { public static string FileExtension => "vcf"; private readonly StreamWriter _writer; public VCard(string filename) : this(filename, Utils.UTF8) { } public VCard(string filename, Encoding encoding) { _writer = new StreamWriter(filename, false, encoding); } public void Dispose() { GC.SuppressFinalize(this); _writer.Dispose(); } public ValueTask DisposeAsync() { GC.SuppressFinalize(this); return _writer.DisposeAsync(); } public async Task ExportAsync(IEnumerable data, IProgress? progress = null) { progress?.Report(0.0); int count = data.Count() + 1, i = 0; foreach (var row in data) { var billingAddr = row.BillingAddress != null ? $"ADR;TYPE=work;LANGUAGE=de;LABEL=\"{Escape(row.BillingAddress.FullName)}\\n{Escape(row.BillingAddress.Address)}\\n{row.BillingAddress.PostalDest.AtPlz?.Plz} {Escape(row.BillingAddress.PostalDest.AtPlz?.Ort.Name)}\\nÖsterreich\":;;{Escape(row.BillingAddress.Address)};{Escape(row.BillingAddress.PostalDest.AtPlz?.Ort.Name)};;{row.BillingAddress.PostalDest.AtPlz?.Plz};Österreich\r\n" : null; var tel = string.Join("", row.TelephoneNumbers .Where(n => n.Type != "fax") .Select(n => $"TEL;TYPE={(n.Type == "mobile" ? "cell" : "voice")}:{Escape(n.Number)}\r\n")); var email = string.Join("", row.EmailAddresses.Select(a => $"EMAIL:{Escape(a.Address)}\r\n")); await _writer.WriteLineAsync($""" BEGIN:VCARD VERSION:4.0 UID:mg{row.MgNr}@{App.Client.NameToken.ToLower()}.elwig.at NOTE:MgNr. {row.MgNr} FN:{Escape(row.AdministrativeName)} N:{Escape(row.Name)};{Escape(row.GivenName)};{Escape(row.MiddleName)};{Escape(row.Prefix)};{Escape(row.Suffix)} KIND:{(row.IsJuridicalPerson ? "org" : "individual")} ADR{(billingAddr == null ? "" : ";TYPE=home")};LANGUAGE=de;LABEL="{Escape(row.Address)}\n{row.PostalDest.AtPlz?.Plz} {Escape(row.PostalDest.AtPlz?.Ort.Name)}\nÖsterreich":;;{Escape(row.Address)};{Escape(row.PostalDest.AtPlz?.Ort.Name)};;{row.PostalDest.AtPlz?.Plz};Österreich {billingAddr}{tel}{email}REV:{row.ModifiedAt.ToUniversalTime():yyyyMMdd\THHmmss\Z} END:VCARD """); progress?.Report(100.0 * ++i / count); } await _writer.FlushAsync(); progress?.Report(100.0); } public void Export(IEnumerable data, IProgress? progress = null) { ExportAsync(data, progress).GetAwaiter().GetResult(); } private static string? Escape(string? text) { return text?.Replace("\\", "\\\\").Replace(",", "\\,").Replace(";", "\\;").Replace("\n", "\\n").Replace("\r", ""); } } }