232 lines
9.6 KiB
C#

using System.Text.Json;
namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class Person
{
// ...
private static List<string> ValidatePerson(Properties.IStorage storage, Models.PersonId id, Models.PersonBirthday birthday, Models.PersonName name)
{
List<string> results = new();
if (birthday is null)
throw new Exception("Birthday must be supplied!");
if (birthday.Value > DateTime.Now)
results.Add("Birthday must be in the past!");
if (id is null)
throw new Exception("Birthday must be supplied!");
if (id.Value != birthday.Value.Ticks)
results.Add("Id must be Birthday ticks!");
if (name.First is null || string.IsNullOrEmpty(name.First.Value))
results.Add("Fist Name must be supplied!");
if (PersonBirthday.DoesBirthDateExits(storage, birthday))
results.Add("BirthDate already exits!");
return results;
}
internal static Models.Person CreatePerson(Properties.IStorage storage, Models.PersonBirthday birthday, Models.PersonName name, List<Models.PersonComment> comments, List<Models.PersonURL> urls, List<Models.PersonNumber> numbers, List<Models.PersonEmail> emails, List<Models.PersonAddress> addresses)
{
Models.Person result;
Models.PersonId id = new(birthday.Value.Ticks);
if (birthday.Value == DateTime.MinValue)
birthday = PersonBirthday.GetNextBirthDate(storage);
List<string> results = ValidatePerson(storage, id, birthday, name);
if (results.Any())
throw new Exception(string.Join(Environment.NewLine, results));
if (comments is null)
comments = new();
if (urls is null)
urls = new();
if (numbers is null)
numbers = new();
if (emails is null)
emails = new();
if (addresses is null)
addresses = new();
result = new(id, birthday, name, comments, urls, numbers, emails, addresses);
return result;
}
internal static Dictionary<DateTime, string[]> Split(string knownPeopleFile)
{
Dictionary<DateTime, string[]> results = new();
string[] segments;
DateTime personKey;
List<string> temporarySegments;
const string KeyFormat = "yyyy-MM-dd_HH";
DateTime incrementDate = new(1500, 1, 1);
string[] lines = File.ReadAllLines(knownPeopleFile);
_ = incrementDate.AddDays(lines.Length);
System.Globalization.CultureInfo cultureInfo = System.Globalization.CultureInfo.InvariantCulture;
foreach (string line in lines)
{
if (string.IsNullOrEmpty(line))
continue;
segments = line.Replace(" //", "\t//").Split('\t');
if (segments.Length < 1)
continue;
if (segments[0].Length != KeyFormat.Length || !segments[0].Contains('-') || !segments[0].Contains('_'))
{
temporarySegments = segments.ToList();
temporarySegments.Insert(0, incrementDate.ToString(KeyFormat));
segments = temporarySegments.ToArray();
incrementDate = incrementDate.AddDays(1);
}
personKey = DateTime.ParseExact(segments[0], KeyFormat, cultureInfo);
if (results.ContainsKey(personKey))
continue;
results.Add(personKey, segments);
}
int countBefore = results.Count;
DateTime minimumDateTime = results.Keys.Min();
for (int i = 1; i < (1000 - countBefore); i++)
{
personKey = minimumDateTime.AddDays(i * -1);
results.Add(personKey, new string[] { personKey.ToString(KeyFormat) });
}
return results.OrderBy(l => l.Key).ToDictionary(l => l.Key, l => l.Value);
}
internal static Dictionary<DateTime, PersonImport> GetPersonCollection(string knownPeopleFile)
{
Dictionary<DateTime, PersonImport> results = new();
string name;
DateTime key;
string comment;
string oldName;
string mergeName;
PersonImport person;
Dictionary<DateTime, string[]> splitLines = Split(knownPeopleFile);
foreach (KeyValuePair<DateTime, string[]> splitLine in splitLines)
{
name = string.Empty;
key = splitLine.Key;
comment = string.Empty;
oldName = string.Empty;
mergeName = string.Empty;
if (splitLine.Value.Length > 1)
{
foreach (string segment in splitLine.Value)
{
if (!segment.Contains('*'))
continue;
mergeName = segment.Split('*')[1].Split('\t')[0];
}
if (splitLine.Value[1].StartsWith("//"))
comment = splitLine.Value[1];
else
name = splitLine.Value[1].Split('\t')[0];
if (splitLine.Value.Length > 2)
comment = splitLine.Value[2];
}
person = new(key, name, mergeName, oldName, comment);
results.Add(splitLine.Key, person);
}
return results;
}
internal static void SavePerson(Properties.IStorage storage, Models.Person person)
{
string fileName = IPerson.GetFileFullName(storage, person);
string json = JsonSerializer.Serialize(person, new JsonSerializerOptions { WriteIndented = true });
_ = IStorage.WriteAllText(fileName, json, updateDateWhenMatches: true, compareBeforeWrite: true);
}
private static List<Models.Person> GetPeopleFromText(Properties.IStorage storage, string localKnownPeopleFile)
{
List<Models.Person> results = new();
string comment;
Models.Person person;
Models.PersonName name;
List<Models.PersonURL> urls;
Models.PersonBirthday birthday;
List<Models.PersonEmail> emails = new();
List<Models.PersonNumber> numbers = new();
List<Models.PersonComment> comments = new();
List<Models.PersonAddress> addresses = new();
Dictionary<DateTime, PersonImport> keyValuePairs = GetPersonCollection(localKnownPeopleFile);
foreach (KeyValuePair<DateTime, PersonImport> keyValuePair in keyValuePairs)
{
if (string.IsNullOrEmpty(keyValuePair.Value.Name))
continue;
urls = new();
birthday = new(keyValuePair.Key);
name = PersonName.Create(keyValuePair.Value.Name);
if (name.First is null || string.IsNullOrEmpty(name.First.Value))
continue;
if (!string.IsNullOrEmpty(keyValuePair.Value.Comment))
{
comment = keyValuePair.Value.Comment[2..];
if (!string.IsNullOrEmpty(comment))
{
if (comment.StartsWith("http://") || comment.StartsWith("https://"))
urls.Add(new(new(comment)));
else
comments.Add(new(new(comment)));
}
}
if (!string.IsNullOrEmpty(keyValuePair.Value.OldName))
comments.Add(new(new(keyValuePair.Value.OldName)));
person = IPerson.CreatePerson(storage, birthday, name, comments, urls, numbers, emails, addresses);
SavePerson(storage, person);
results.Add(person);
}
return results;
}
internal static Models.Person[] GetPeople(Properties.IStorage storage)
{
List<Models.Person> results = new();
string json;
string[] files;
FileInfo fileInfo;
Models.Person? person;
string localKnownPeopleFile;
DateTime dateTime = DateTime.MinValue;
string directory = Path.Combine(storage.PeopleRootDirectory, "{}");
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
string? rootDirectoryParent = Path.GetDirectoryName(storage.RootDirectory);
if (string.IsNullOrEmpty(rootDirectoryParent))
throw new NullReferenceException(nameof(rootDirectoryParent));
if (!Directory.Exists(rootDirectoryParent))
localKnownPeopleFile = string.Empty;
else
{
files = Directory.GetFiles(rootDirectoryParent, "*People*.txt", SearchOption.TopDirectoryOnly);
if (files.Any())
localKnownPeopleFile = files[0];
else
localKnownPeopleFile = string.Empty;
}
files = Directory.GetFiles(directory, "*.json", SearchOption.TopDirectoryOnly);
if (!files.Any() && string.IsNullOrEmpty(localKnownPeopleFile))
throw new Exception("Copy \"KnownPeople.txt\" file from server!");
foreach (string file in files)
{
fileInfo = new(file);
if (dateTime < fileInfo.LastWriteTime)
dateTime = fileInfo.LastWriteTime;
json = File.ReadAllText(file);
person = JsonSerializer.Deserialize<Models.Person>(json);
if (person is null)
continue;
results.Add(person);
}
if (!results.Any())
results = GetPeopleFromText(storage, localKnownPeopleFile);
else if (!string.IsNullOrEmpty(localKnownPeopleFile))
{
fileInfo = new FileInfo(localKnownPeopleFile);
if (fileInfo.LastWriteTime > dateTime)
{
foreach (string file in files)
File.Delete(file);
results = GetPeopleFromText(storage, localKnownPeopleFile);
}
}
return results.ToArray();
}
}