/*
 * Copyright 2013 NEHTA
 *
 * Licensed under the NEHTA Open Source (Apache) License; you may not use this
 * file except in compliance with the License. A copy of the License is in the
 * 'license.txt' file, which should be provided with this work.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

using System;
using System.Collections.Generic;
using System.Xml;
using Nehta.VendorLibrary.CDA.Generator.Enums;
using Nehta.VendorLibrary.CDA.SCSModel.Common.Entities;
using Nehta.VendorLibrary.Common;
using Nehta.VendorLibrary.CDA.Generator;
using Nehta.VendorLibrary.CDA.Common.Enums;
using Nehta.VendorLibrary.CDA.Common;
using Nehta.VendorLibrary.CDA.SCSModel;
using Nehta.VendorLibrary.CDA.SCSModel.Common;

namespace Nehta.VendorLibrary.CDA.Sample
{
    /// <summary>
    /// This project is intended to demonstrate how an EventSummary CDA document can be created.
    /// 
    /// The project contains two samples, the first is designed to create a fully populated CDA document, including
    /// all of the optional sections and entries. The second sample only populates the mandatory sections and entries.
    /// 
    /// The CDA model is split into three distinct sections, each of which needs to be created via the 
    /// EventSummary class, and then populated with data as appropriate. The three sections that need to be
    /// created and hydrated with data are:
    /// 
    ///     CDA Context (Clinical Document Architecture - Context)
    ///     SCS Context (Structured Document Template - Context)
    ///     SCS Content (Structured Document Template - Content)
    /// 
    /// The CDA Context typically contains information that is to be represented within the header of the document
    /// that is not encapsulated with the SCS context.
    /// E.g. Generic CDA sections or entries; for example custodian.
    /// 
    /// The SCS Context typically contains information that is to be represented within the header of the document
    /// and relates specifically to the type of document that is to be created.
    /// E.g. E-Referral specific CDA sections or entries; for example Subject of Care.
    /// 
    /// The SCS Content typically contains information that is to be represented with the body of the document.
    /// </summary>
    public class EventSummarySample
    {
        #region Properties

        public static string OutputFolderPath { get; set; }

        public static String OutputFileNameAndPath
        {
            get
            {
                return OutputFolderPath + @"\EventSummary.xml";
            }
        }

        public static String ImageFileNameAndPath
        {
            get
            {
                return OutputFolderPath + @"\x-ray.jpg";
            }
        }

        public static String PitNameAndPath
        {
            get
            {
                return OutputFolderPath + @"\PIT.txt";
            }
        }

        public static String StructuredFileAttachment
        {
            get
            {
                return OutputFolderPath + @"\attachment.pdf";
            }
        }

        public static String ResultFileNameAndPath
        {
            get
            {
                return OutputFolderPath + @"\path1234.pdf";
            }
        }

        // Note: Place this in any string field and and this will insert a break
        private const String DELIMITERBREAK = "<BR>";

        #endregion

        /// <summary>
        /// This sample populates only the mandatory sections / entries
        /// </summary>
        public XmlDocument MinPopulatedEventSummary(string fileName)
        {
            XmlDocument xmlDoc = null;

            var eEventSummary = PopulatedEventSummary(true);

            try
            {
                CDAGenerator.NarrativeGenerator = new CDANarrativeGenerator();

                //Pass the Event Summary model into the GenerateEventSummary method 
                xmlDoc = CDAGenerator.GenerateEventSummary(eEventSummary);

                using (var writer = XmlWriter.Create(OutputFolderPath + @"\" + fileName, new XmlWriterSettings { Indent = true }))
                {
                    if (!fileName.IsNullOrEmptyWhitespace()) xmlDoc.Save(writer);
                }
            }
            catch (ValidationException ex)
            {
                //Catch any validation exceptions
                var validationMessages = ex.GetMessagesString();

                //Handle any validation errors as appropriate.
                throw;
            }

            return xmlDoc;
        }

        /// <summary>
        /// This example populates only the mandatory Sections / Entries; as a result this sample omits all
        /// of the content within the body of the CDA document; as each of the sections within the body
        /// are optional.
        /// </summary>
        public XmlDocument PopulateEventSummarySample_1A(string fileName)
        {
            XmlDocument xmlDoc = null;

            var document = PopulatedEventSummary(true);
            document.SCSContent = EventSummary.CreateSCSContent();

            document.IncludeLogo = false;

            var structuredBodyFileList = new List<ExternalData>();

            var structuredBodyFile = BaseCDAModel.CreateStructuredBodyFile();
            structuredBodyFile.Caption = "Structured Body File";
            structuredBodyFile.ExternalDataMediaType = MediaType.PDF;
            structuredBodyFile.Path = StructuredFileAttachment;
            structuredBodyFileList.Add(structuredBodyFile);

            document.SCSContent.StructuredBodyFiles = structuredBodyFileList;

            try
            {
                CDAGenerator.NarrativeGenerator = new CDANarrativeGenerator();

                //Pass the document model into the Generate method 
                xmlDoc = CDAGenerator.GenerateEventSummary(document);

                using (var writer = XmlWriter.Create(OutputFolderPath + @"\" + fileName, new XmlWriterSettings() { Indent = true }))
                {
                    if (!fileName.IsNullOrEmptyWhitespace()) xmlDoc.Save(writer);
                }
            }
            catch (ValidationException ex)
            {
                //Catch any validation exceptions
                var validationMessages = ex.GetMessagesString();

                //Handle any validation errors as appropriate.
                throw;
            }

            return xmlDoc;
        }

        /// <summary>
        /// This sample populates both the mandatory and optional Sections / Entries; as a result this sample
        /// includes all of the sections within the body and each section includes at least one example for 
        /// each of its optional entries
        /// </summary>
        public XmlDocument MaxPopulatedEventSummary(string fileName)
        {
            XmlDocument xmlDoc = null;

            var eEventSummary = PopulatedEventSummary(false);

            try
            {
                CDAGenerator.NarrativeGenerator = new CDANarrativeGenerator();

                //Pass the Event Summary model into the GenerateEventSummary method 
                xmlDoc = CDAGenerator.GenerateEventSummary(eEventSummary);

                using (var writer = XmlWriter.Create(OutputFolderPath + @"\" + fileName, new XmlWriterSettings() { Indent = true }))
                {
                    if (!fileName.IsNullOrEmptyWhitespace()) xmlDoc.Save(writer);
                }
            }
            catch (ValidationException ex)
            {
                //Catch any validation exceptions
                var validationMessages = ex.GetMessagesString();

                //Handle any validation errors as appropriate.
                throw;
            }

            return xmlDoc;
        }

        /// <summary>
        /// This example populates only the mandatory Sections / Entries; as a result this sample ommits all
        /// of the non mandatory content.
        /// </summary>
        public XmlDocument PopulatedEventSummary()
        {
            XmlDocument xmlDoc = null;

            var eEventSummary = PopulatedEventSummary(true);

            try
            {
                CDAGenerator.NarrativeGenerator = new CDANarrativeGenerator();

                xmlDoc = CDAGenerator.GenerateEventSummary(eEventSummary);

                xmlDoc.Save(OutputFileNameAndPath);
            }
            catch (ValidationException ex)
            {
                //Catch any validation exceptions
                var validationMessages = ex.GetMessagesString();

                //Handle any validation errors as appropriate.
            }
            return xmlDoc;
        }

        #region Private Test Methods

        /// <summary>
        /// This sample populates both the mandatory and optional Sections / Entries depenting on the  
        /// mandatorySectionsOnly boolean
        /// </summary>
        internal static EventSummary PopulatedEventSummary(Boolean mandatorySectionsOnly)
        {
            var eventSummary = EventSummary.CreateEventSummary();

            // Include Logo
            eventSummary.IncludeLogo = true;

            // Set Creation Time
            eventSummary.DocumentCreationTime = new ISO8601DateTime(DateTime.Now);

            #region Setup and populate the CDA context model

            // Setup and populate the CDA context model
            var cdaContext = EventSummary.CreateCDAContext();
            // Document Id
            cdaContext.DocumentId = BaseCDAModel.CreateIdentifier(BaseCDAModel.CreateOid(), null);
            // Set Id  
            cdaContext.SetId = BaseCDAModel.CreateIdentifier(BaseCDAModel.CreateGuid(), null);
            // CDA Context Version
            cdaContext.Version = "1";

            // Custodian
            cdaContext.Custodian = EventSummary.CreateCustodian();
            GenericObjectReuseSample.HydrateCustodian(cdaContext.Custodian, mandatorySectionsOnly);

            cdaContext.LegalAuthenticator = EventSummary.CreateLegalAuthenticator();
            GenericObjectReuseSample.HydrateAuthenticator(cdaContext.LegalAuthenticator, mandatorySectionsOnly);

            eventSummary.CDAContext = cdaContext;
            #endregion

            #region Setup and Populate the SCS Context model
            // Setup and Populate the SCS Context model

            eventSummary.SCSContext = EventSummary.CreateSCSContext();

            eventSummary.SCSContext.Author = EventSummary.CreateAuthor();
            GenericObjectReuseSample.HydrateAuthor(eventSummary.SCSContext.Author, mandatorySectionsOnly);

            eventSummary.SCSContext.SubjectOfCare = EventSummary.CreateSubjectOfCare();
            GenericObjectReuseSample.HydrateSubjectofCare(eventSummary.SCSContext.SubjectOfCare, mandatorySectionsOnly);

            if (!mandatorySectionsOnly)
            {
                eventSummary.SCSContext.EncounterPeriod = BaseCDAModel.CreateInterval("12", TimeUnitOfMeasure.Month);
            }
              else
            {
                eventSummary.SCSContext.EncounterPeriodNullFlavor = NullFlavour.NegativeInfinity;
            }

            #endregion

            #region Setup and populate the SCS Content model
            // Setup and populate the SCS Content model
            eventSummary.SCSContent = EventSummary.CreateSCSContent();

            if (!mandatorySectionsOnly)
            {
                eventSummary.SCSContent.EventDetails = CreateEventDetails();

                // Adverse reactions
                eventSummary.SCSContent.AdverseReactions = CreateAdverseReactions();

                // Medications
                eventSummary.SCSContent.Medications = CreateMedications();

                // Medical history
                eventSummary.SCSContent.DiagnosesIntervention = CreateDiagnosesIntervention();

                // Immunisations
                eventSummary.SCSContent.Immunisations = CreateImmunisations();

                // Diagnostic Investigations
                eventSummary.SCSContent.DiagnosticInvestigations = CreateDiagnosticInvestigations(mandatorySectionsOnly);
            }

            #endregion

            return eventSummary;
        }

        /// <summary>
        /// Creates and Hydrates a Reference Range
        /// </summary>
        /// <param name="code">The Code</param>
        /// <param name="name">The Name</param>
        /// <param name="units">The Unit</param>
        /// <param name="high">The high value</param>
        /// <param name="low">The Low Quantity</param>
        /// <returns>A Hydrated ResultValueReferenceRangeDetail object</returns>
        private static ResultValueReferenceRangeDetail CreateReferenceRange(String code, String name, String units, Double? high, Double? low)
        {
            var resultValueReferenceRangeDetail = EventSummary.CreateResultValueReferenceRangeDetail();
            resultValueReferenceRangeDetail.Range = EventSummary.CreateQuantityRange();
            resultValueReferenceRangeDetail.Range.High = high;
            resultValueReferenceRangeDetail.Range.Low = low;
            resultValueReferenceRangeDetail.Range.Units = units;
            resultValueReferenceRangeDetail.ResultValueReferenceRangeMeaning = EventSummary.CreateResultValueReferenceRangeMeaning
                                                                                (
                                                                                    code,
                                                                                    CodingSystem.SNOMED,
                                                                                    name,
                                                                                    null,
                                                                                    null
                                                                                );

            return resultValueReferenceRangeDetail;
        }

        /// <summary>
        /// Creates and Hydrates a PhysicalDetails object
        /// </summary>
        /// <param name="value">The Quantity</param>
        /// <param name="units">The Unit</param>
        /// <returns>A Hydrated PhysicalDetails object</returns>
        private static PhysicalDetails CreatePhysicalDetails(string value, String units)
        {
            PhysicalDetails physicalDetails = null;

            if (!value.IsNullOrEmptyWhitespace() && !units.IsNullOrEmptyWhitespace())
            {
                physicalDetails = EventSummary.CreatePhysicalDetails();

                physicalDetails.Volume = EventSummary.CreateQuantity();
                physicalDetails.Volume.Value = value;
                physicalDetails.Volume.Units = units;
            }


            return physicalDetails;
        }

        /// <summary>
        /// Creates and Hydrates Event Details
        /// </summary>
        /// <returns>A Hydrated IImagingExaminationResult object</returns>
        private static EventDetails CreateEventDetails()
        {
            var eventDetails = EventSummary.CreateEventDetails();
            eventDetails.ClinicalSynopsisDescription = EventSummary.CreateReasonForEncounterDescription("35933005", CodingSystem.SNOMED, "laceration", "laceration", null);
            return eventDetails;
        }

        /// <summary>
        /// Creates and Hydrates the immunisations section for the Event Summary
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated Event Summary object</returns>
        private static List<IImmunisation> CreateImmunisations()
        {
            var immunisationList = new List<IImmunisation>
            {

                CreateImmunisation(DateTime.Parse("22 Dec 2009"), "53705011000036109", CodingSystem.AMT, "Advil (ibuprofen 200 mg) tablet: sugar-coated, 1 tablet", null),
                CreateImmunisation(DateTime.Parse("3 Oct 2010"), "66071002", CodingSystem.SNOMED, "Hepatitis B", 1)
            };
 
            return immunisationList;
        }

      /// <summary>
      /// Creates an immunisation.
      /// </summary>
      /// <param name="date">Date of immunisation.</param>
      /// <param name="code">Code of immunisation.</param>
      /// <param name="codingSystem">Coding system for the code.</param>
      /// <param name="name">Name of immunisation.</param>
      /// <param name="sequenceNumber">The immunisation sequence number </param>
      /// <returns>Created immunisation.</returns>
      private static IImmunisation CreateImmunisation(DateTime date, string code, CodingSystem codingSystem, string name, int? sequenceNumber)
        {
            var immunisation = EventSummary.CreateImmunisation();
            immunisation.DateTime = new ISO8601DateTime(date);
            immunisation.Medicine = EventSummary.CreateMedicine(code, codingSystem, name, null, null);
            immunisation.SequenceNumber = sequenceNumber;
            return immunisation;
        }

        /// <summary>
        /// Creates and Hydrates the Medications section for the Event Summary
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated List of Medications</returns>
        private static List<IMedicationItem> CreateMedications()
        {
            var medicationList = new List<IMedicationItem>
                                     {
                                         CreateMedication("23641011000036102", "paracetamol 500 mg + codeine phosphate 30 mg tablet", NullFlavour.NegativeInfinity, NullFlavour.PositiveInfinity, NullFlavour.NoInformation),
                                         CreateMedication("45260011000036108", "dextropropoxyphene hydrochloride 32.5 mg + paracetamol 325 mg tablet", null, null, null)
                                     };

            return medicationList;
        }

      /// <summary>
      /// Creates a medication item.
      /// </summary>
      /// <param name="code">Medication code.</param>
      /// <param name="name">Medication name.</param>
      /// <param name="directionsNullFlavour">The Directions Null Flavour</param>
      /// <param name="recomendationOrChangeNullFlavour">The Recomendation Or Change Null Flavour</param>
      /// <param name="changeTypeNullFlavour">The Change Type Null Flavour</param>
      /// <returns></returns>
      private static IMedicationItem CreateMedication(string code, string name, NullFlavour? directionsNullFlavour, NullFlavour? recomendationOrChangeNullFlavour, NullFlavour? changeTypeNullFlavour)
        {
            IMedicationItem medication = EventSummary.CreateMedication();

            if (directionsNullFlavour.HasValue)
              medication.DirectionsNullFlavour = directionsNullFlavour;
            else
              medication.Directions = "As directed by packaging.";

            if (recomendationOrChangeNullFlavour.HasValue)
              medication.RecommendationOrChangeNullFlavour = recomendationOrChangeNullFlavour;
            else
              medication.RecommendationOrChange = RecomendationOrChange.TheChangeHasBeenMade;

            if (changeTypeNullFlavour.HasValue)
              medication.ChangeTypeNullFlavour = changeTypeNullFlavour;
            else
              medication.ChangeType = ChangeType.Unchanged;

            //medication.ChangeDescription = "ChangeDescription";
            medication.ChangeReason = "ChangeReason";
            medication.ClinicalIndication = "ClinicalIndication";
            medication.Comment = "Comment";

            medication.Medicine = EventSummary.CreateMedicine
                (
                    code,
                    CodingSystem.AMT,
                    name,
                    null,
                    null
                );

            return medication;
        }

        /// <summary>
        /// Creates and Hydrates the Medications section for the Event Summary
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated List of RequestedService</returns>
        private static List<RequestedService> CreateRequestedService(Boolean mandatorySectionsOnly)
        {
            var requestedServiceList = new List<RequestedService>();

            // Create Service Provider for a Person
            var requestedServicePerson = EventSummary.CreateRequestedService();
            requestedServicePerson.ServiceCommencementWindow = EventSummary.CreateInterval(
                new ISO8601DateTime(DateTime.Now, ISO8601DateTime.Precision.Day), 
                new ISO8601DateTime(DateTime.Now.AddMonths(6), ISO8601DateTime.Precision.Day));
            requestedServicePerson.RequestedServiceDescription = EventSummary.CreateRequestedServiceDescription("399208008", CodingSystem.SNOMED, "chest x-ray", null, null);
            requestedServicePerson.ServiceBookingStatus = EventTypes.Definition;
            requestedServicePerson.SubjectOfCareInstructionDescription = "Subject Of Care Instruction Description";
            requestedServicePerson.RequestedServiceDateTime = new ISO8601DateTime(DateTime.Now.AddDays(4), ISO8601DateTime.Precision.Day);
            requestedServicePerson.ServiceProvider = CreateServiceProviderPerson(mandatorySectionsOnly);

            // Add to list
            requestedServiceList.Add(requestedServicePerson);

            // Create Service Provider for a Organisation
            var requestedServiceOrganisation = EventSummary.CreateRequestedService();
            requestedServiceOrganisation.ServiceScheduled = new ISO8601DateTime(DateTime.Now);
            requestedServiceOrganisation.RequestedServiceDescription = EventSummary.CreateRequestedServiceDescription("399208008", CodingSystem.SNOMED, "chest x-ray", null, null);
            requestedServiceOrganisation.ServiceBookingStatus = EventTypes.Intent;
            requestedServiceOrganisation.SubjectOfCareInstructionDescription = "Subject Of Care Instruction Description";
            requestedServiceOrganisation.RequestedServiceDateTime = new ISO8601DateTime(DateTime.Now.AddDays(4));
            requestedServiceOrganisation.ServiceProvider = CreateServiceProviderOrganisation(mandatorySectionsOnly);

            // Add to list
            requestedServiceList.Add(requestedServiceOrganisation);

            return requestedServiceList;
        }

        /// <summary>
        /// Creates and Hydrates a Service Provider Organisation
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated IParticipationHealthProfessional object</returns>
        private static IParticipationServiceProvider CreateServiceProviderOrganisation(Boolean mandatorySectionsOnly)
        {
            var serviceProvider = EventSummary.CreateServiceProvider();

            serviceProvider.Participant = EventSummary.CreateParticipantForServiceProvider();
            serviceProvider.Participant.Organisation= EventSummary.CreateOrganisation();
            serviceProvider.Participant.Organisation.Name = "Bay Hill Hospital";
            serviceProvider.Participant.Organisation.NameUsage = OrganisationNameUsage.Other;

            serviceProvider.Participant.Organisation.Identifiers = new List<Identifier> { BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.HPIO, "8003620000045562") }; 

            var electronicCommunicationDetail = EventSummary.CreateElectronicCommunicationDetail(
                "0345754566",
                ElectronicCommunicationMedium.Telephone,
                ElectronicCommunicationUsage.WorkPlace);

            serviceProvider.Participant.ElectronicCommunicationDetails = new List<ElectronicCommunicationDetail> { electronicCommunicationDetail, electronicCommunicationDetail };

            var address = EventSummary.CreateAddress();
            address.AddressPurpose = AddressPurpose.Residential;
            address.AustralianAddress = EventSummary.CreateAustralianAddress();
            address.AustralianAddress.UnstructuredAddressLines = new List<string> { "1 Clinician Street" };
            address.AustralianAddress.SuburbTownLocality = "Nehtaville";
            address.AustralianAddress.State = AustralianState.QLD;
            address.AustralianAddress.PostCode = "5555";
            address.AustralianAddress.DeliveryPointId = 32568931;

            if (!mandatorySectionsOnly)
            {
              serviceProvider.Role = BaseCDAModel.CreateRole(Occupation.GeneralMedicalPractitioner);
            }
            else
            {
              serviceProvider.Role = BaseCDAModel.CreateRole(NullFlavour.Other);
            }

            serviceProvider.Participant.Addresses = new List<IAddress> 
            { 
                address, address 
            };

            return serviceProvider;
        }

        /// <summary>
        /// Creates and Hydrates a Service Provider Person
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated IParticipationHealthProfessional object</returns>
        private static IParticipationServiceProvider CreateServiceProviderPerson(Boolean mandatorySectionsOnly)
        {
            var serviceProvider = EventSummary.CreateServiceProvider();

            var participant = EventSummary.CreateParticipantForServiceProvider();
            participant.Person = EventSummary.CreatePersonForServiceProvider();

            var personName = BaseCDAModel.CreatePersonName();
            personName.FamilyName = "Dr Jane Anderson";
            personName.NameUsages = new List<NameUsage> { NameUsage.Legal };
            participant.Person.Identifiers = new List<Identifier> { BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.HPII, "8003610000001145") }; 
            participant.Person.PersonNames = new List<IPersonName> { personName };
            participant.Person.Organisation = BaseCDAModel.CreateEmploymentOrganisation();
            participant.Person.Organisation.Name = "Hay Bill Hospital (ServiceProviderPerson)";
            participant.Person.Organisation.NameUsage = OrganisationNameUsage.Other;
            participant.Person.Organisation.Identifiers = new List<Identifier> { BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.HPIO, "8003620000045562") };
            participant.Person.Organisation.Department = "Some department service provider";
            participant.Person.Organisation.EmploymentType = EventSummary.CreateCodableText(null, null, null, "Service Provider Casual", null);
            participant.Person.Organisation.Occupation = Occupation.TyreFitter;
            participant.Person.Organisation.PositionInOrganisation = EventSummary.CreateCodableText(null, null, null, "Service Provider Manager", null);            


            participant.ElectronicCommunicationDetails = new List<ElectronicCommunicationDetail> 
            { 
                EventSummary.CreateElectronicCommunicationDetail("0345754566", ElectronicCommunicationMedium.Telephone, ElectronicCommunicationUsage.WorkPlace), 
                EventSummary.CreateElectronicCommunicationDetail("1234", ElectronicCommunicationMedium.Email, ElectronicCommunicationUsage.Home)
            };

            var address = EventSummary.CreateAddress();
            address.AddressPurpose = AddressPurpose.Business;
            address.AustralianAddress = EventSummary.CreateAustralianAddress();
            address.AustralianAddress.UnstructuredAddressLines = new List<string> { "1 Clinician Street" };
            address.AustralianAddress.SuburbTownLocality = "Nehtaville";
            address.AustralianAddress.State = AustralianState.QLD;
            address.AustralianAddress.PostCode = "5555";
            address.AustralianAddress.DeliveryPointId = 32568931;

            if (!mandatorySectionsOnly)
            {
              serviceProvider.Role = BaseCDAModel.CreateRole(Occupation.GeneralMedicalPractitioner);
            } 
              else
            {
              serviceProvider.Role = BaseCDAModel.CreateRole(NullFlavour.NegativeInfinity);
            }

            participant.Addresses = new List<IAddress>
            {
                address, address
            };

            serviceProvider.Participant = participant;

            return serviceProvider;
        }

        /// <summary>
        /// Creates and Hydrates the Diagnoses Intervention section for the Event Summary
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated DiagnosesIntervention object</returns>
        private static DiagnosesIntervention CreateDiagnosesIntervention()
        {
            var diagnosesInterventions = EventSummary.CreateDiagnosesInterventions();

            var interval = BaseCDAModel.CreateInterval(
                                new ISO8601DateTime(DateTime.Now.AddDays(-400), ISO8601DateTime.Precision.Day),
                                new ISO8601DateTime(DateTime.Now.AddDays(200), ISO8601DateTime.Precision.Day));

            interval.ShowOngoingInNarrative = true;

            var medicalHistoryItems = new List<IMedicalHistoryItem>
            {
                CreateMedicalHistoryItem("Medical history comment goes here", "Medical history item goes here", BaseCDAModel.CreateInterval(
                    new ISO8601DateTime(DateTime.Now.AddDays(-200), ISO8601DateTime.Precision.Day),
                    new ISO8601DateTime(DateTime.Now.AddDays(200), ISO8601DateTime.Precision.Day))),

                CreateMedicalHistoryItem("Another medical history comment goes here", "Another medical history item goes here", interval)
            };

            var procedureList = new List<Procedure>
            {
                CreateProcedure("Procedure comment goes here.", "120214004", "Anaesthesia for procedure on perineum", new ISO8601DateTime(DateTime.Now.AddDays(-12))),
                CreateProcedure("Another procedure comment.", "26268001", "Anastomosis of hepatic ducts", null)
            };

            var diagnosisList = new List<IProblemDiagnosisEventSummary>
            {
                CreateProblemDiagnosis("Problem/Diagnosis comment goes here.", "168942008", "Abdominal aortogram normal", new ISO8601DateTime(DateTime.Now.AddDays(100))),
                CreateProblemDiagnosis("Another Problem/Diagnosis comment goes here.", "187079000", "Chromoblastomycosis", new ISO8601DateTime(DateTime.Now.AddDays(-500)))
            };

            diagnosesInterventions.Procedures = procedureList;
            diagnosesInterventions.MedicalHistoryItem = medicalHistoryItems;
            diagnosesInterventions.ProblemDiagnosis = diagnosisList;

            return diagnosesInterventions;
        }

        /// <summary>
        /// Creates a problem diagnosis.
        /// </summary>
        /// <param name="comment">Problem diagnosis comment.</param>
        /// <param name="code">Problem diagnosis code.</param>
        /// <param name="name">Problem diagnosis name.</param>
        /// <returns></returns>
        private static IProblemDiagnosisEventSummary CreateProblemDiagnosis(string comment, string code, string name, ISO8601DateTime dateOfOnset)
        {
            var diagnois = EventSummary.CreateProblemDiagnosis();
            diagnois.Comment = comment;
            diagnois.ProblemDiagnosisIdentification = EventSummary.CreateProblemDiagnosisIdentification(code, CodingSystem.SNOMED, name, null);
            diagnois.DateOfOnset = dateOfOnset;
            return diagnois;
        }

        /// <summary>
        /// Creates a procedure.
        /// </summary>
        /// <param name="comment">Procedure comemnt.</param>
        /// <param name="code">Procedure code.</param>
        /// <param name="name">Procedure name.</param>
        /// <returns></returns>
        private static Procedure CreateProcedure(string comment, string code, string name, ISO8601DateTime date)
        {
            var procedure = EventSummary.CreateProcedure();
            procedure.Comment = comment;
            procedure.ProcedureName = EventSummary.CreateProcedureName(code, CodingSystem.SNOMED, name, null, null);
            procedure.Start = date;
            return procedure;
        }

        /// <summary>
        /// Creates a medication history item.
        /// </summary>
        /// <param name="comment">Medication history item comment.</param>
        /// <param name="description">Medication history item description.</param>
        /// <returns></returns>
        private static IMedicalHistoryItem CreateMedicalHistoryItem(string comment, string description, CdaInterval interval)
        {
            var medicalHistoryItem = EventSummary.CreateMedicalHistoryItem();
            medicalHistoryItem.DateTimeInterval = interval; 
            medicalHistoryItem.ItemDescription = description;
            medicalHistoryItem.ItemComment = comment;
            return medicalHistoryItem;
        }

        /// <summary>
        /// Creates and Hydrates the adverse substance reactions section for the Event Summary
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated List of IAdverseReactionsEventSummay object</returns>
        private static IAdverseReactionsWithoutExclusions CreateAdverseReactions()
        {
            var reactions = EventSummary.CreateAdverseReactions();

            reactions.AdverseSubstanceReaction = new List<Reaction>
                                                     {
                                                         CreateAdverseReaction("86461001", "Plant diterpene"),
                                                         CreateAdverseReaction("117491007", "trans-Nonachlor")
                                                     };
            
            return reactions;
        }

        /// <summary>
        /// Creates an adverse reaction.
        /// </summary>
        /// <param name="code">Code for the adverse reaction.</param>
        /// <param name="name">Name of the adverse reaction.</param>
        /// <returns></returns>
        private static Reaction CreateAdverseReaction(string code, string name)
        {
            Reaction reaction = EventSummary.CreateReaction();

            reaction.SubstanceOrAgent = EventSummary.CreateSubstanceOrAgent
                (
                    code,
                    CodingSystem.SNOMED,
                    name,
                    name,
                    null
                );

            reaction.ReactionEvent = EventSummary.CreateReactionEvent();
            reaction.ReactionEvent.Manifestations = new List<ICodableText>
            {
                EventSummary.CreateManifestation
                (
                    "248265004",
                    CodingSystem.SNOMED,
                    "Work stress",
                    null,
                    null
                ),
                EventSummary.CreateManifestation
                (
                    "425392003",
                    CodingSystem.SNOMED,
                    "Active advance directive",
                    null,
                    null
                )
            };

            return reaction;
        }

        /// <summary>
        /// Creates and hydrates the diagnostic investigations section.
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A hydrated 'DiagnosticInvestigations' object.</returns>
        private static IDiagnosticInvestigations CreateDiagnosticInvestigations(Boolean mandatorySectionsOnly)
        {
            IDiagnosticInvestigations diagnosticInvestigations = EventSummary.CreateDiagnosticInvestigations();

            diagnosticInvestigations.ImagingExaminationResult = new List<IImagingExaminationResult>
                                                                {
                                                                    GenericObjectReuseSample.CreateImagingResults("Leg Image"),
                                                                    GenericObjectReuseSample.CreateImagingResults("Head Image")
                                                                };

            // Pathology test results
            diagnosticInvestigations.PathologyTestResult = new List<PathologyTestResult> 
                                                           {
                                                                GenericObjectReuseSample.CreatePathologyResults("Chemisty studies (set)", PitNameAndPath),
                                                                GenericObjectReuseSample.CreatePathologyResults("Blood studies (set)")
                                                           };

            // Other Test Result 
            diagnosticInvestigations.OtherTestResult = new List<OtherTestResult>
                                                       {
                                                              GenericObjectReuseSample.CreateOtherTestResultAttachment(),
                                                              GenericObjectReuseSample.CreateOtherTestResultText()
                                                       };
      
            // Requested Service
            diagnosticInvestigations.RequestedService = CreateRequestedService(mandatorySectionsOnly);

            return diagnosticInvestigations;
        }

        #endregion
    }
}