/// <summary>
        /// Create a synchronization context
        /// </summary>
        public static SynchronizationContext CreateContext()
        {
            try
            {
                Trace.TraceInformation("Create Synchrnoization Job Data");
                // Register
                using (var dao = new SyncData())
                {
                    // Sync context
                    var retVal = new SynchronizationContext()
                    {
                        JobId     = dao.CreateSynchronizationJob(Process.GetCurrentProcess().Id),
                        StartTime = DateTime.Now
                    };

                    Trace.TraceInformation("DB: Registered sync job id #{0}", retVal.JobId);
                    dao.Commit();
                    return(retVal);
                }
            }
            catch (Exception e)
            {
                Trace.TraceError(e.ToString());
                return(null);
            }
            finally
            {
            }
        }
        /// <summary>
        /// Mark sync as error
        /// </summary>
        public void Error()
        {
            try
            {
                Trace.TraceInformation("Marking Synchrnoization Job Error");

                // Register
                using (var dao = new SyncData())
                {
                    this.Success  = false;
                    this.StopTime = DateTime.Now;
                    dao.CompleteSynchronizationJob(this.JobId, false);
                    dao.Commit();
                }
            }
            catch (Exception e)
            {
                Trace.TraceError(e.ToString());
            }
            finally
            {
            }
        }
        /// <summary>
        /// Process PID data async manner
        /// </summary>
        private void ProcessPIDAsync(object state)
        {
            try
            {
                var responseData           = state as RSP_K21_QUERY_RESPONSE;
                GIIS.DataLayer.Child child = null;

                // Now sync patient data if they don't exist

                // Is there a GIIS identifier in the list of identifiers for this patient?
                String ecidIdentifier = responseData.PID.GetPatientIdentifierList().Where(id => id.AssigningAuthority.UniversalID.Value == ConfigurationManager.AppSettings["ecid"]).Select(o => o.IDNumber.Value).First();

                List <String> localGiisIdentifier = responseData.PID.GetPatientIdentifierList().Where(id => id.AssigningAuthority.UniversalID.Value == ConfigurationManager.AppSettings["giis_child_id_oid"]).Select(o => o.IDNumber.Value).ToList();

                // If there is a local GIIS identifier! The patient exists in GIIS
                if (localGiisIdentifier.Count > 0)
                {
                    var children = localGiisIdentifier.Select(o => GIIS.DataLayer.Child.GetChildById(Int32.Parse(o))).ToList();
                    children.RemoveAll(o => o == null);
                    if (children.Count == 0)
                    {
                        Trace.TraceInformation("{0} : No children records found with local ID, maybe they're gone?", this.m_context.JobId);
                        return;
                    }

                    // Find the child that has the ECID
                    using (var dao = new SyncData())
                    {
                        // Get the survivor or the only
                        child = children.FirstOrDefault(o => o != null && o.IsActive && dao.GetChildEcid(o.Id) == ecidIdentifier);
                        if (child == null && children.Count == 1)
                        {
                            child = children.First();
                            children.Clear();
                        }
                        else
                        {
                            children.RemoveAll(o => o.Id == child.Id && child.IsActive);
                        }

                        // Is the record in the CR newer than the record in GIIS?
                        if (((TS)responseData.PID.LastUpdateDateTime.Time.Value).DateValue.Date > child.ModifiedOn.Date.AddDays(1))
                        {
                            // Register that we've updated this patient in the sync log
                            Trace.TraceInformation("{0} : Updating child record {1}", this.m_context.JobId, child.Id);

                            // Copy fields
                            this.CopyChildRecordFields(child, responseData.PID);
                            // Now update
                            GIIS.DataLayer.Child.Update(child);
                            dao.RegisterPatientSync(child.Id, this.m_context.JobId, ActionType.Update, ecidIdentifier);
                        }
                        else
                        {
                            Trace.TraceWarning("{0} : Child record {1} in GIIS appears to be up to date", this.m_context.JobId, child.Id);
                            //return;
                        }

                        // Merge patient data
                        if (children.Count > 0)
                        {
                            // Load all completed vaccinations/appointments/weights for the survivor
                            var survivorsVaccinationEvents          = GIIS.DataLayer.VaccinationEvent.GetImmunizationCard(child.Id).Where(o => o.VaccinationStatus || o.NonvaccinationReasonId != 0).ToList();
                            var survivorsNonVaccinationAppointments = GIIS.DataLayer.VaccinationEvent.GetImmunizationCard(child.Id).Where(o => !o.VaccinationStatus && o.NonvaccinationReasonId == 0).Select(o => o.Appointment).Distinct(new VaccinationAppointmentComparator());
                            var survivorsWeightEvents = GIIS.DataLayer.ChildWeight.GetChildWeightByChildId(child.Id);
                            var survivorsSupplements  = GIIS.DataLayer.ChildSupplements.GetChildSupplementsByChild(child.Id);

                            // Now we want to add vaccination events
                            foreach (var victim in children)
                            {
                                Trace.TraceInformation("Merging CHILD {0} INTO {1}", victim.Id, child.Id);
                                // GEt all victim's vaccination events that were not given to the survivor
                                IEnumerable victimsVaccinationEvents = GIIS.DataLayer.VaccinationEvent.GetImmunizationCard(victim.Id)
                                                                       .Where(o => (o.VaccinationStatus || o.NonvaccinationReasonId != 0) &&
                                                                              !survivorsVaccinationEvents.Exists(s => s.DoseId == o.DoseId)),
                                            victimsWeightEvents = GIIS.DataLayer.ChildWeight.GetChildWeightByChildId(victim.Id);
                                var victimSupplements           = GIIS.DataLayer.ChildSupplements.GetChildSupplementsByChild(victim.Id);

                                // Now we want to copy from victim to survivor
                                foreach (GIIS.DataLayer.VaccinationEvent victimEvent in victimsVaccinationEvents)
                                {
                                    victimEvent.ChildId    = child.Id;
                                    victimEvent.ModifiedBy = Int32.Parse(ConfigurationManager.AppSettings["giis_authority_user_id"]);
                                    victimEvent.ModifiedOn = DateTime.Now;
                                    GIIS.DataLayer.VaccinationEvent.Insert(victimEvent);
                                }

                                // Now copy weights over
                                foreach (GIIS.DataLayer.ChildWeight weight in victimsWeightEvents)
                                {
                                    weight.ChildId    = child.Id;
                                    weight.ModifiedBy = Int32.Parse(ConfigurationManager.AppSettings["giis_authority_user_id"]);
                                    weight.ModifiedOn = DateTime.Now;
                                    GIIS.DataLayer.ChildWeight.Insert(weight);
                                }

                                // Supplements
                                if (survivorsSupplements != null)
                                {
                                    survivorsSupplements.Mebendezol = victimSupplements.Mebendezol || survivorsSupplements.Mebendezol;
                                    survivorsSupplements.Vita       = victimSupplements.Vita || survivorsSupplements.Vita;
                                    GIIS.DataLayer.ChildSupplements.Update(survivorsSupplements);
                                }

                                // Obsolete the old version
                                victim.StatusId = GIIS.DataLayer.Status.GetStatusByName("Duplicate").Id;
                                GIIS.DataLayer.Child.Update(victim);

                                GIIS.DataLayer.ChildMerges mergeData = new GIIS.DataLayer.ChildMerges();
                                mergeData.ChildId       = child.Id;
                                mergeData.SubsumedId    = victim.Id;
                                mergeData.EffectiveDate = DateTime.Now;
                                GIIS.DataLayer.ChildMerges.Insert(mergeData);
                            }
                        }

                        dao.Commit();
                    }
                }
                else // We need to create the child record in GIIS
                {
                    Trace.TraceInformation("{0} : Creating child record from ECID {1}", this.m_context.JobId, ecidIdentifier);

                    // Child
                    child = new GIIS.DataLayer.Child();
                    this.CopyChildRecordFields(child, responseData.PID);

                    try
                    {
                        // Is the child older than the last vaccination? If so we don't really care
                        if (GIIS.DataLayer.Dose.GetDosesByDates(child.Birthdate).Count == 0)
                        {
                            Trace.TraceInformation("Don't care about this child as they don't have any vaccinations required");
                            return;
                        }

                        child.Id = GIIS.DataLayer.Child.Insert(child);
                        GIIS.DataLayer.VaccinationAppointment.InsertVaccinationsForChild(child.Id, 1);

                        // Register the patient in the PIX manager
                        // Register the fact we create the child in the sync log
                        using (var dao = new SyncData())
                        {
                            dao.RegisterPatientSync(child.Id, this.m_context.JobId, ActionType.Create, ecidIdentifier);
                            ADT_A01 message  = this.CreateADT(child, dao);
                            var     response = this.m_sender.SendAndReceive(message) as NHapi.Model.V231.Message.ACK;
                            AuditUtil.SendPIXAudit(message, response);
                            if (!response.MSA.AcknowledgementCode.Value.EndsWith("A"))
                            {
                                Trace.TraceError("{0} : Registration of the patient failed in CR");
                                foreach (var er in response.ERR.GetErrorCodeAndLocation())
                                {
                                    Trace.TraceError("{0} : ERR {1}", this.m_context.JobId, er.CodeIdentifyingError.Text.Value);
                                }
                            }
                            dao.Commit();
                        }
                    }
                    catch (Exception e)
                    {
                        Trace.TraceError("{0} : Error registering child record: {1}", this.m_context.JobId, e);
                    }
                }
            }
            catch (Exception e)
            {
                Trace.TraceInformation(e.ToString());
                this.m_errorState = true;
            }
        }
        /// <summary>
        /// Process a response message doing query continuation if needed
        /// </summary>
        private void PushPatientsAsync(Object state)
        {
            Int32 childId = (Int32)state;

            // Get the child record
            try
            {
                GIIS.DataLayer.Child child = GIIS.DataLayer.Child.GetChildById(childId);


                // Determine if this is an update to information (A08) or registration (A04)
                using (var dao = new SyncData())
                {
                    ADT_A01 request = this.CreateADT(child, dao);

                    ActionType action = ActionType.Create;
                    String     ecid   = dao.GetPatientEcid(childId);
                    if (ecid == null) // no ECID = Register
                    {
                        this.UpdateMSH(request.MSH, "ADT_A01", "ADT", "A04");
                    }
                    else
                    {
                        this.UpdateMSH(request.MSH, "ADT_A01", "ADT", "A08");
                        action = ActionType.Update;
                    }

                    // Send the message
                    var response = this.m_sender.SendAndReceive(request) as NHapi.Model.V231.Message.ACK;
                    AuditUtil.SendPIXAudit(request, response);
                    if (response == null || !response.MSA.AcknowledgementCode.Value.EndsWith("A"))
                    {
                        Trace.TraceError("{0}: Error registering the child in HIE (child id#{1})", this.m_context.JobId, childId);
                        foreach (var err in response.ERR.GetErrorCodeAndLocation())
                        {
                            Trace.TraceError("{0}: CR ERR: {1} ({2})", this.m_context.JobId, err.CodeIdentifyingError.Text, err.CodeIdentifyingError.AlternateText);
                        }
                        // Kill!
                        Trace.TraceError("Stopping sync");
                        this.m_errorState = true;
                        return;
                    }

                    // Get the ECID if not already got
                    if (action == ActionType.Create)
                    {
                        var pixSearch   = this.CreatePIXSearch(child.Id, ConfigurationManager.AppSettings["giis_child_id_oid"], ConfigurationManager.AppSettings["ecid"]);
                        var pixResponse = this.m_sender.SendAndReceive(pixSearch) as RSP_K23;
                        AuditUtil.SendPIXAudit(pixSearch, pixResponse);
                        // Is the response success?
                        if (pixResponse == null || pixResponse.QAK.QueryResponseStatus.Value != "OK")
                        {
                            Trace.TraceError("{0}: Error retrieving the ECID for created patient", this.m_context.JobId);
                            foreach (var err in pixResponse.ERR.GetErrorCodeAndLocation())
                            {
                                Trace.TraceError("{0}: CR ERR: {1} ({2})", this.m_context.JobId, err.CodeIdentifyingError.Text, err.CodeIdentifyingError.AlternateText);
                            }
                            // Kill!
                            Trace.TraceError("Stopping sync");
                            this.m_errorState = true;
                            return;
                        }
                        else
                        {
                            var cx = pixResponse.QUERY_RESPONSE.PID.GetPatientIdentifierList(0);
                            // Sanity check
                            if (cx.AssigningAuthority.UniversalID.Value.Equals(ConfigurationManager.AppSettings["ecid"]))
                            {
                                ecid = cx.IDNumber.Value;
                            }
                            else
                            {
                                Trace.TraceError("{0}: Should not be here! CX.4 indicates ECID OID is {1} but configuration is {2}?", this.m_context.JobId, cx.AssigningAuthority.UniversalID.Value, ConfigurationManager.AppSettings["ecid"]);
                                this.m_errorState = true;
                                return;
                            }
                        }
                    }

                    // Update
                    if (String.IsNullOrEmpty(child.TempId))
                    {
                        child.TempId = ecid;
                    }

                    child.ModifiedOn = DateTime.Now;
                    child.ModifiedBy = Int32.Parse(ConfigurationManager.AppSettings["giis_authority_user_id"]);
                    GIIS.DataLayer.Child.Update(child);

                    dao.RegisterPatientSync(childId, this.m_context.JobId, action, ecid);
                    dao.Commit();
                }
            }
            catch (Exception e)
            {
                Trace.TraceError(e.ToString());
                this.m_errorState = true;
            }
        }