package xyz.driver.pdsuidomain.formats.json.sprayformats
import java.time.LocalDateTime
import java.util.UUID
import spray.json._
import xyz.driver.core.json.{EnumJsonFormat, GadtJsonFormat}
import xyz.driver.pdsuicommon.domain.{LongId, TextJson, UuidId}
import xyz.driver.pdsuidomain.entities._
object record {
import DefaultJsonProtocol._
import MedicalRecord._
import common._
implicit val recordStatusFormat = new EnumJsonFormat[Status](
"Unprocessed" -> Status.Unprocessed,
"PreOrganized" -> Status.PreOrganized,
"New" -> Status.New,
"Cleaned" -> Status.Cleaned,
"PreOrganized" -> Status.PreOrganized,
"PreOrganizing" -> Status.PreOrganizing,
"Reviewed" -> Status.Reviewed,
"Organized" -> Status.Organized,
"Done" -> Status.Done,
"Flagged" -> Status.Flagged,
"Archived" -> Status.Archived
)
implicit val requestIdFormat = new RootJsonFormat[RecordRequestId] {
override def write(requestId: RecordRequestId): JsString = JsString(requestId.toString)
override def read(json: JsValue): RecordRequestId = json match {
case JsString(value) => RecordRequestId(UUID.fromString(value))
case _ => deserializationError(s"Expected string as RecordRequestId, but got $json")
}
}
implicit val caseIdFormat = new RootJsonFormat[CaseId] {
override def write(caseId: CaseId): JsString = JsString(caseId.toString)
override def read(json: JsValue): CaseId = json match {
case JsString(value) => CaseId(value)
case _ => deserializationError(s"Expected string as CaseId, but got $json")
}
}
implicit val recordMetaTypeFormat: GadtJsonFormat[MedicalRecord.Meta] = {
import Meta._
GadtJsonFormat.create[Meta]("meta")({ case m => m.metaType }) {
case "duplicate" => jsonFormat5(Duplicate.apply)
case "reorder" => jsonFormat2(Reorder.apply)
case "rotation" => jsonFormat2(Rotation.apply)
}
}
implicit val recordMetaFormat = new RootJsonFormat[TextJson[List[Meta]]] {
override def write(obj: TextJson[List[Meta]]): JsArray = JsArray(obj.content.map(_.toJson).toVector)
override def read(json: JsValue): TextJson[List[Meta]] = json match {
case JsArray(values) => TextJson[List[Meta]](values.map(_.convertTo[Meta]).toList)
case _ => deserializationError(s"Expected array as Meta, but got $json")
}
}
implicit val recordFormat: RootJsonFormat[MedicalRecord] =
new RootJsonFormat[MedicalRecord] {
override def write(record: MedicalRecord): JsValue =
JsObject(
"id" -> record.id.id.toJson,
"patientId" -> record.patientId.toJson,
"caseId" -> record.caseId.toJson,
"disease" -> record.disease.toJson,
"physician" -> record.physician.toJson,
"status" -> record.status.toJson,
"previousStatus" -> record.previousStatus.toJson,
"assignee" -> record.assignee.toJson,
"previousAssignee" -> record.previousAssignee.toJson,
"requestId" -> record.requestId.toJson,
"meta" -> record.meta.getOrElse(TextJson[List[Meta]](List.empty)).toJson,
"lastActiveUser" -> record.lastActiveUserId.toJson,
"lastUpdate" -> record.lastUpdate.toJson
)
override def read(json: JsValue): MedicalRecord = json match {
case JsObject(fields) =>
val disease = fields
.get("disease")
.map(_.convertTo[String])
.getOrElse(deserializationError(s"MedicalRecord json object does not contain `disease` field: $json"))
val patientId = fields
.get("patientId")
.map(_.convertTo[UuidId[Patient]])
.getOrElse(deserializationError(s"MedicalRecord json object does not contain `patientId` field: $json"))
val requestId = fields
.get("requestId")
.map(_.convertTo[RecordRequestId])
.getOrElse(deserializationError(s"MedicalRecord json object does not contain `requestId` field: $json"))
MedicalRecord(
id = LongId(0),
status = MedicalRecord.Status.New,
previousStatus = None,
assignee = None,
previousAssignee = None,
lastActiveUserId = None,
patientId = patientId,
requestId = requestId,
disease = disease,
caseId = None,
physician = None,
meta = None,
predictedMeta = None,
predictedDocuments = None,
lastUpdate = LocalDateTime.now()
)
case _ => deserializationError(s"Expected Json Object as MedicalRecord, but got $json")
}
}
def applyUpdateToMedicalRecord(json: JsValue, orig: MedicalRecord): MedicalRecord = json match {
case JsObject(fields) =>
val meta = if (fields.contains("meta")) {
fields
.get("meta")
.map(_.convertTo[TextJson[List[Meta]]])
} else orig.meta
orig.copy(meta = meta)
case _ => deserializationError(s"Expected Json Object as partial MedicalRecord, but got $json")
}
}