using adas_core.Domain.Enums; using adas_core.Domain.Models.MongoModels; namespace adas_core.Domain.Models; /// /// Represents a person, providing type-specific equality comparison between instances. /// /// /// Implements to define a strongly typed Equals(T)"/> method for comparing objects. /// public class Person : IEquatable { public string? LastName { get; set; } public string? FirstName { get; set; } public string? SecondName { get; set; } public DateTime? BirthDate { get; set; } public string? Language { get; set; } public PatientEnum.Gender Gender { get; set; } = PatientEnum.Gender.Unknown; public Dictionary? Ids { get; set; } public List? HistoricalIds { get; set; } /// /// Determines whether the current instance is equal to another by comparing their last name, first name, second name, birth date, language, gender, and identifiers. /// Returns false when the specified other person is null. /// /// The to compare with the current instance. /// true if all compared personal attributes and identifiers match; otherwise, false. public bool Equals(Person? other) { return other != null && LastName == other.LastName && FirstName == other.FirstName && SecondName == other.SecondName && BirthDate == other.BirthDate && Language == other.Language && Gender == other.Gender && CheckIdsAreEqual(other); } /// /// Sets the current patient identifiers and records them in the historical identifier list. If a historical entry already exists for the target time, the provided identifiers are merged into it; otherwise a new entry is created. When is null, the current UTC date and time is used, and the historical list is lazily initialized if needed. /// /// The dictionary of patient identifiers to assign as the current identifiers and to record historically. /// The optional timestamp for the historical entry. If null, is used. public void SetIds(Dictionary patientIds, DateTime? time = null) { Ids = patientIds; HistoricalIds ??= new List(); DateTime targetTime = time ?? DateTime.UtcNow; var existingOption = HistoricalIds.FirstOrDefault(c => c.Time == targetTime); if (existingOption != null) { foreach (var kvp in patientIds) { existingOption.PatientIds[kvp.Key] = kvp.Value; } } else { HistoricalIds.Add(new HistoricalId(targetTime, new Dictionary(patientIds))); } } /// /// Determines whether the patient instance contains no meaningful data by checking that the last name, first name, second name, and birth date are unset, the gender is unknown, and the identifiers collection is null or empty. /// /// true if all relevant patient fields are null, empty, or set to their default unknown value; otherwise, false. public bool IsEmpty() { return string.IsNullOrEmpty(LastName) && string.IsNullOrEmpty(FirstName) && string.IsNullOrEmpty(SecondName) && BirthDate == null && Gender == PatientEnum.Gender.Unknown && (Ids == null || Ids.Count == 0); } /// /// Determines whether the patient record contains no personal information, ignoring identification fields. /// Returns true only when all personal data fields (last name, first name, second name, birth date) are null or empty /// and the gender is set to . /// /// true if the patient's personal data fields are empty and gender is unknown; otherwise, false. public bool IsEmptyDontCheckIds() { return string.IsNullOrEmpty(LastName) && string.IsNullOrEmpty(FirstName) && string.IsNullOrEmpty(SecondName) && BirthDate == null && Gender == PatientEnum.Gender.Unknown; } //public override bool Equals(object? obj) //{ // return Equals(obj as Person); //} /// /// Determines whether the identifier collection of the current is equal to that of another instance, handling cases where either or both collections are null and verifying matching keys and values. /// /// The other whose identifiers are compared against this instance. /// true if both identifier collections are null or contain the same key-value pairs; otherwise, false. private bool CheckIdsAreEqual(Person other) { if (Ids == null && other.Ids == null) return true; if (Ids == null || other.Ids == null) return false; if (Ids.Count != other.Ids.Count) return false; foreach (var kvp in Ids) if (!other.Ids.TryGetValue(kvp.Key, out var otherValue) || otherValue != kvp.Value) return false; return true; } //public override int GetHashCode() //{ // var hashCode = -373112803; // if (LastName != null) // hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(LastName); // if (FirstName != null) // hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(FirstName); // if (SecondName != null) // hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(SecondName); // if (BirthDate != null) hashCode = hashCode * -1521134295 + BirthDate.GetHashCode(); // if (Language != null) // hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Language); // hashCode = hashCode * -1521134295 + Gender.GetHashCode(); // if (Ids != null) // hashCode = hashCode * -1521134295 + EqualityComparer>.Default.GetHashCode(Ids); // return hashCode; //} /// /// Returns a string representation of the Person, including the non-empty/non-null properties such as first name, last name, second name, birth date, language, gender, and identifiers. /// /// A formatted string in the form "Person[prop1: value1, prop2: value2, ...]" containing the person's populated fields. public override string ToString() { List items = []; if (!string.IsNullOrEmpty(FirstName)) items.Add($"firstName: {FirstName}"); if (!string.IsNullOrEmpty(LastName)) items.Add($", lastName: {LastName}"); if (!string.IsNullOrEmpty(SecondName)) items.Add($"secondName: {SecondName}"); if (BirthDate.HasValue) items.Add($"birthDate: {BirthDate}"); if (!string.IsNullOrEmpty(Language)) items.Add($"language: {Language}"); items.Add($"gender: {Gender}"); if (Ids?.Count > 0) items.Add($"ids: {string.Join(',', Ids.Select(i => $"[{i.Key}:{i.Value}]"))}"); return "Person[" + string.Join(", ", items) + "]"; } }