using System.Reflection; using adas_core.Domain.Enums; using MongoDB.Bson; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; namespace adas_core.Domain.Models; /// /// Provides custom JSON serialization and deserialization logic for instances by inheriting from . /// /// /// This converter overrides the default JSON conversion behavior to control how objects are written to and read from JSON. /// public class PatientTreatment : JsonConverter { //If bolopom plus to bolus opiates. public bool BoloPom = false; //If single Dose is true, finish at end of actual shift. public bool SingleDose = false; public ObjectId Id { get; set; } public ObjectId PatientId { get; set; } // ORC Common Order public OrderControlType OrderControl { get; set; } public Entity? PlacerOrder { get; set; } public Entity? FillerOrder { get; set; } public string OrderStatus { get; set; } = string.Empty; public DateTime? OrderTime { get; set; } public DateTime? EndTime { get; set; } public DateTime? StartTime { get; set; } // RXO Pharmacy/Treatment Route public List RequestedGiveCodes { get; set; } = []; public string RequestedGiveTreatment { get; set; } = string.Empty; // RXA - Pharmacy/Treatment Administration public List RequestedGiveCodesStatus { get; set; } = []; public double? RequestedGiveAmountMinimum { get; set; } public double? RequestedGiveAmountMaximum { get; set; } public Code? RequestedGiveUnits { get; set; } public Code? RequestedDosageForm { get; set; } // NTE Notes and comments public List Notes { get; set; } = []; // RXR Pharmacy/Treatment Route public List Routes { get; set; } = []; //MSH Time of HL7 public DateTime MessageTime { get; set; } public string? SystemId { get; set; } /// /// Returns a string representation of the PatientTreatment instance, including its core identifiers, order details, timing fields, requested give codes, notes, and routes. Non-null or non-empty properties are appended to the output, and in case of an exception during formatting, an error message containing the exception detail is returned instead. /// /// A formatted string summarizing the PatientTreatment fields, or an error message if formatting fails. public override string ToString() { try { List items = [ $"id: {Id}", $"patientid: {PatientId}", $"orderControl: {OrderControl}" ]; if (PlacerOrder != null) items.Add($"placerOrder: {PlacerOrder}"); if (FillerOrder != null) items.Add($"fillerOrder: {FillerOrder}"); if (!string.IsNullOrEmpty(OrderStatus)) items.Add($"orderStatus: {OrderStatus}"); if (OrderTime != null) items.Add($"orderTime: {OrderTime}"); if (StartTime != null) items.Add($"startTime: {StartTime}"); if (EndTime != null) items.Add($"endTime: {EndTime}"); if (RequestedGiveCodes.Any()) RequestedGiveCodes.ForEach(c => items.Add($"RequestedGiveCodes: {c}")); if (!string.IsNullOrEmpty(RequestedGiveTreatment)) items.Add($"requestedGiveTreatment: {RequestedGiveTreatment}"); if (RequestedGiveCodesStatus.Any()) RequestedGiveCodesStatus.ForEach(c => items.Add($"{c}")); if (RequestedGiveAmountMinimum != null) items.Add($"requestedGiveAmountMinimum: {RequestedGiveAmountMinimum}"); if (RequestedGiveAmountMaximum != null) items.Add($"requestedGiveAmountMaximum: {RequestedGiveAmountMaximum}"); if (RequestedGiveUnits != null) items.Add($"requestedGiveUnits: {RequestedGiveUnits}"); if (RequestedDosageForm != null) items.Add($"requestedDosageForm: {RequestedDosageForm}"); Notes.ForEach(n => items.Add($"{n}")); Routes.ForEach(r => items.Add($"{r}")); items.Add($"singleDose: {SingleDose}"); items.Add($"boloPom: {BoloPom}"); items.Add($"messageTime: {MessageTime}"); if (!string.IsNullOrEmpty(SystemId)) items.Add($"systemId: {SystemId}"); return "PatientTreatment[" + string.Join(", ", items) + "]"; } catch (Exception ex) { //Log.Error("Error parsing PatientTreatment to string. Exception: {ex}", ex); return "Error deserielizing:" + ex.Message; } } /// /// Serializes the specified value to JSON, converting the property to its string representation via . /// If the value is null, nothing is written to the JSON output. /// /// The to which the JSON representation of the value will be written. /// The object to serialize. If null, the method performs no action. /// The used to perform the serialization of nested objects. public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value != null) { var jo = JObject.FromObject(value); // Add [JsonConverter(typeof(StringEnumConverter))] attribute to specified properties AddStringEnumConverterAttribute(value, nameof(OrderControl)); jo.WriteTo(writer); } } /// /// Adds a JsonConverterAttribute of type StringEnumConverter to the specified property if one is not already applied. The method performs no action if the property cannot be found or if a JsonConverterAttribute is already present. /// /// The object instance whose property should receive the attribute. /// The name of the property to which the attribute will be added. private static void AddStringEnumConverterAttribute(object value, string propertyName) { var prop = value.GetType().GetProperty(propertyName); var attr = new JsonConverterAttribute(typeof(StringEnumConverter)); if (prop != null) { var attrs = prop.GetCustomAttributes(false); // Check if the attribute is not already applied if (Array.Find(attrs, a => a is JsonConverterAttribute) == null) { // Create a new array that includes the existing attributes and the new one var newAttrs = new object[attrs.Length + 1]; Array.Copy(attrs, newAttrs, attrs.Length); newAttrs[attrs.Length] = attr; // Use reflection to set the new attributes array var field = typeof(PropertyInfo).GetField("m_customAttributes", BindingFlags.Instance | BindingFlags.NonPublic); field?.SetValue(prop, newAttrs); } } } /// /// Reads the JSON representation of the specified type. This conversion is not currently implemented and will always raise an exception. /// /// The used to read the incoming JSON tokens. /// The target type of the object being deserialized. /// The existing value of the object that is being populated, or if none exists. /// The invoking this converter. /// An object of the specified type deserialized from the JSON. /// Always thrown because the method has not been implemented. public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } /// /// Determines whether the converter can convert the specified type. /// /// The type to check for conversion support. /// if the converter can convert the specified type; otherwise, . /// Always thrown because the method is not yet implemented. public override bool CanConvert(Type objectType) { throw new NotImplementedException(); } }