/*
 * 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.IO;
using System.Linq;
using Nehta.VendorLibrary.CDA.Common;
using Nehta.VendorLibrary.CDA.Common.Enums;
using Nehta.VendorLibrary.CDA.Generator.Enums;
using Nehta.VendorLibrary.CDA.SCSModel;
using Nehta.VendorLibrary.CDA.SCSModel.Common;
using Nehta.VendorLibrary.CDA.SCSModel.Common.Entities;
using Nehta.VendorLibrary.CDA.SCSModel.DischargeSummary;
using Nehta.VendorLibrary.Common;

namespace Nehta.VendorLibrary.CDA.Sample
{
    /// <summary>
    /// Demonstrates the reuse of header objects in the CDA Libary 
    /// </summary>
    public class GenericObjectReuseSample
    {
      #region Properties

      public static string OutputFolderPath { get; set; }

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

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

      #endregion


        /// <summary>
        /// Creates and Hydrates an Subject Of Care demonstating its usage with multiple CDA Libaries 
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated SubjectOfCare</returns>
        public IParticipationSubjectOfCare PopulateSubjectOfCare()
        {
            IParticipationSubjectOfCare genericSubjectOfCare = BaseCDAModel.CreateSubjectOfCare();

            HydrateSubjectofCare(genericSubjectOfCare, false);

            //The requirement to instantiate the objects with the factory ensures that the correct implementations
            //of each interface are instantiated; e.g. that the correct content and context are created.
            var specialistLetter = new SpecialistLetter(DocumentStatus.Interim)
                                       {
                                           SCSContext = SpecialistLetter.CreateSCSContext()
                                       };

            specialistLetter.SCSContext.SubjectOfCare = genericSubjectOfCare;

            //The requirement to instantiate the objects with the factory ensures that the correct implementations
            //of each interface are instantiated; e.g. that the correct content and context are created.
            var dischargeSummary = new EDischargeSummary(DocumentStatus.Interim)
                                       {
                                           SCSContext = EDischargeSummary.CreateSCSContext()
                                       };

            dischargeSummary.SCSContext.SubjectOfCare = genericSubjectOfCare;

            return genericSubjectOfCare;
        }

        /// <summary>
        /// Creates and Hydrates an Author demonstating its usage with multiple CDA Libaries 
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated Author</returns>
        public IParticipationDocumentAuthor PopulateAuthor()
        {
            IParticipationDocumentAuthor genericAuthor = BaseCDAModel.CreateAuthor();

            HydrateAuthor(genericAuthor, false);

            //The requirement to instantiate the objects with the factory ensures that the correct implementations
            //of each interface are instantiated; e.g. that the correct content and context are created.
            var specialistLetter = new SpecialistLetter(DocumentStatus.Interim)
            {
                SCSContext = SpecialistLetter.CreateSCSContext()
            };

            specialistLetter.SCSContext.Author = genericAuthor;

            return genericAuthor;
        }

        /// <summary>
        /// Creates and Hydrates an Authenticator demonstating its usage with multiple CDA Libaries 
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated Authenticator</returns>
        public IParticipationLegalAuthenticator PopulateAuthenticator()
        {
            var genericAuthenticator = BaseCDAModel.CreateAuthenticator();

            HydrateAuthenticator(genericAuthenticator, false);

            //The requirement to instantiate the objects with the factory ensures that the correct implementations
            //of each interface are instantiated; e.g. that the correct content and context are created.
            var specialistLetter = new SpecialistLetter(DocumentStatus.Interim)
            {
                CDAContext = SpecialistLetter.CreateCDAContext()
            };

            specialistLetter.CDAContext.LegalAuthenticator = genericAuthenticator;

            //The requirement to instantiate the objects with the factory ensures that the correct implementations
            //of each interface are instantiated; e.g. that the correct content and context are created.
            var dischargeSummary = new EDischargeSummary(DocumentStatus.Interim)
            {
                CDAContext = EDischargeSummary.CreateCDAContext()
            };

            dischargeSummary.CDAContext.LegalAuthenticator = genericAuthenticator;

            return genericAuthenticator;
        }

        /// <summary>
        /// Creates and Hydrates an Custodian demonstating its usage with multiple CDA Libaries 
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated Custodian</returns>
        public IParticipationCustodian PopulateCustodian()
        {
            IParticipationCustodian genericCustodian = BaseCDAModel.CreateCustodian();

            HydrateCustodian(genericCustodian, false);

            //The requirement to instantiate the objects with the factory ensures that the correct implementations
            //of each interface are instantiated; e.g. that the correct content and context are created.
            var specialistLetter = new SpecialistLetter(DocumentStatus.Interim)
            {
                CDAContext = SpecialistLetter.CreateCDAContext()
            };

            specialistLetter.CDAContext.Custodian = genericCustodian;

            //The requirement to instantiate the objects with the factory ensures that the correct implementations
            //of each interface are instantiated; e.g. that the correct content and context are created.
            var dischargeSummary = new EDischargeSummary(DocumentStatus.Interim)
            {
                CDAContext = EDischargeSummary.CreateCDAContext()
            };

            dischargeSummary.CDAContext.Custodian = genericCustodian;

            return genericCustodian;
        }

        /// <summary>
        /// Creates and Hydrates an Recipient demonstating its usage with multiple CDA Libaries 
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated Recipient</returns>
        public IParticipationInformationRecipient PopulateRecipient()
        {
            var genericRecipient = BaseCDAModel.CreateInformationRecipient();

            HydrateRecipient(genericRecipient, RecipientType.Primary, false);

            //The requirement to instantiate the objects with the factory ensures that the correct implementations
            //of each interface are instantiated; e.g. that the correct content and context are created.
            var specialistLetter = new SpecialistLetter(DocumentStatus.Interim)
            {
                CDAContext = SpecialistLetter.CreateCDAContext()
            };

            specialistLetter.CDAContext.InformationRecipients = new List<IParticipationInformationRecipient>
            {
                genericRecipient
            };

            //The requirement to instantiate the objects with the factory ensures that the correct implementations
            //of each interface are instantiated; e.g. that the correct content and context are created.
            var dischargeSummary = new EDischargeSummary(DocumentStatus.Interim)
            {
                CDAContext = EDischargeSummary.CreateCDAContext()
            };

            dischargeSummary.CDAContext.InformationRecipients = new List<IParticipationInformationRecipient>
            {
                genericRecipient
            };

            return genericRecipient;
        }
        
        /// <summary>
        /// Creates and Hydrates a Extended SubjectofCare
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated SubjectofCare</returns>
        public static void HydrateExtendedSubjectofCare(IParticipationSubjectOfCare subjectOfCare, bool mandatoryOnly)
        {
            HydrateSubjectofCare(subjectOfCare, mandatoryOnly);

            if (!mandatoryOnly)
            {
                // Subject of Care > Participant > Person or Organisation or Device > Person > Source Of Death Notification
                subjectOfCare.Participant.Person.SourceOfDeathNotification = SourceOfDeathNotification.Relative;

                var mothersOriginalFamilyName = BaseCDAModel.CreatePersonName();
                mothersOriginalFamilyName.FamilyName = "Jones";

                // Subject of Care > Participant > Person or Organisation or Device > Person > Mothers Original Family Name
                subjectOfCare.Participant.Person.MothersOriginalFamilyName = mothersOriginalFamilyName;
            }
        }

        /// <summary>
        /// Creates and Hydrates an SubjectofCare
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated SubjectofCare</returns>
        public static void HydrateSubjectofCare(IParticipationSubjectOfCare subjectOfCare, bool mandatoryOnly)
        {
            var participant = BaseCDAModel.CreateParticipantForSubjectOfCare();

            // Subject of Care > Participant > Person or Organisation or Device > Person
            var person = BaseCDAModel.CreatePersonForSubjectOfCare();

            // Subject of Care > Participant > Address
            var address1 = BaseCDAModel.CreateAddress();

            address1.AddressPurpose = AddressPurpose.Residential;
            address1.AustralianAddress = BaseCDAModel.CreateAustralianAddress();
            
            var address2 = BaseCDAModel.CreateAddress();
            address2.AddressPurpose = AddressPurpose.TemporaryAccommodation;
            address2.InternationalAddress = BaseCDAModel.CreateInternationalAddress();
            
            participant.Addresses = new List<IAddress> { address1, address2 };

            // Subject of Care > Participant > Person or Organisation or Device > Person > Person Name
            var name1 = BaseCDAModel.CreatePersonName();
            name1.FamilyName = "Grant";
            name1.GivenNames = new List<string> { "Sally", "Wally" };
            name1.Titles = new List<string> { "Miss" };
            name1.NameUsages = new List<NameUsage> { NameUsage.Legal };

            var name2 = BaseCDAModel.CreatePersonName();
            name2.FamilyName = "Grant";
            name2.GivenNames = new List<string> { "Wally" };
            name2.Titles = new List<string> { "Mr" };
            name2.NameUsages = new List<NameUsage> { NameUsage.NewbornName };

            person.PersonNames = new List<IPersonName> { name1, name2 };

            // Subject of Care > Participant > Person or Organisation or Device > Person > Demographic Data > Sex
            person.Gender = Gender.Female;

            // Subject of Care > Participant > Person or Organisation or Device > Person > Demographic Data > Date of Birth Detail > 
            // Date of Birth
            person.DateOfBirth = new ISO8601DateTime(DateTime.Now.AddYears(-57));
            
            // Subject of Care > Participant > Person or Organisation or Device > Person > Demographic Data > Indigenous Status
            person.IndigenousStatus = IndigenousStatus.NeitherAboriginalNorTorresStraitIslanderOrigin;   

            // Subject of Care > Participant > Electronic Communication Detail
            var coms1 = BaseCDAModel.CreateElectronicCommunicationDetail(
                "0345754566",
                ElectronicCommunicationMedium.Telephone,
                ElectronicCommunicationUsage.WorkPlace);

            var coms2 = BaseCDAModel.CreateElectronicCommunicationDetail(
                "authen@globalauthens.com",
                ElectronicCommunicationMedium.Email,
                ElectronicCommunicationUsage.WorkPlace);

            participant.ElectronicCommunicationDetails = new List<ElectronicCommunicationDetail> { coms1, coms2 };

            // Subject of Care > Participant > Entity Identifier
            person.Identifiers = new List<Identifier> 
                { 
                     BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.IHI, "8003604444567894"),
                     BaseCDAModel.CreateMedicalRecordNumber("123456", "1.2.3.4", "Croydon GP Centre"),
                     BaseCDAModel.CreateMedicareNumber(MedicareNumberType.MedicareCardNumber,"1234567881")
                };

            if (!mandatoryOnly)
            {
                address1.AustralianAddress.UnstructuredAddressLines = new List<string> { "1 Clinician Street" };
                address1.AustralianAddress.SuburbTownLocality = "Nehtaville";
                address1.AustralianAddress.State = AustralianState.NSW;
                address1.AustralianAddress.PostCode = "5555";
                address1.AustralianAddress.DeliveryPointId = 32568931;
                
                address2.InternationalAddress.AddressLine = new List<string> { "1 Overseas Street" };
                address2.InternationalAddress.Country = Country.NewCaledonia;
                address2.InternationalAddress.PostCode = "12345";
                address2.InternationalAddress.StateProvince = "Foreign Land";

                person.DateOfBirthCalculatedFromAge = true;
                person.DateOfBirthAccuracyIndicator = new DateAccuracyIndicator(true, true, true);
                person.Age = 54;
                person.AgeUnitOfMeasure = AgeUnitOfMeasure.Year;

                person.AgeAccuracyIndicator = true;
                person.BirthPlurality = 3;
                person.BirthOrder = 2;
                person.DateOfDeath = new ISO8601DateTime(DateTime.Now, ISO8601DateTime.Precision.Day);
                person.DateOfDeathAccuracyIndicator = new DateAccuracyIndicator(true, true, true);
                person.CountryOfBirth = Country.Australia;
                person.StateOfBirth = AustralianState.QLD;
                
                // Subject of Care > Participant > Entitlement
                var entitlement1 = BaseCDAModel.CreateEntitlement();
                entitlement1.Id = BaseCDAModel.CreateMedicareNumber(MedicareNumberType.MedicareCardNumber, "1234567881");
                entitlement1.Type = EntitlementType.MedicareBenefits;                
                entitlement1.ValidityDuration = BaseCDAModel.CreateInterval("1", TimeUnitOfMeasure.Year);

                var entitlement2 = BaseCDAModel.CreateEntitlement();
                entitlement2.Id = BaseCDAModel.CreateMedicareNumber(MedicareNumberType.MedicareCardNumber, "2244567891");
                entitlement2.Type = EntitlementType.MedicareBenefits;
                entitlement2.ValidityDuration = BaseCDAModel.CreateInterval("1", TimeUnitOfMeasure.Year);

                participant.Entitlements = new List<Entitlement> { entitlement1, entitlement2 };

            } else
            {
              address1.AddressAbsentIndicator = AddressAbsentIndicator.NoFixedAddressIndicator;
              address2.AddressAbsentIndicator = AddressAbsentIndicator.NoFixedAddressIndicator;
            }

            participant.Person = person;
            subjectOfCare.Participant = participant;
        }

        /// <summary>
        /// Creates and Hydrates an author
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated author</returns>
        public static void HydrateAuthor(IParticipationDocumentAuthor author, bool mandatoryOnly)
        {
            var person = BaseCDAModel.CreatePersonWithOrganisation();

            // Document Author > Role
            author.Role = BaseCDAModel.CreateRole(Occupation.GeneralMedicalPractitioner);

            // Document Author > Participant
            author.Participant = BaseCDAModel.CreateParticipantForAuthor();

            // Document Author > Participant > Entity Identifier
            person.Identifiers = new List<Identifier> { 
                BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.HPII, "8003615833334118") 
            };

            // Document Author > Participant > Address
            var address1 = BaseCDAModel.CreateAddress();
            address1.AddressAbsentIndicator = AddressAbsentIndicator.NoFixedAddressIndicator;
            address1.AddressPurpose = AddressPurpose.Residential;
            address1.AustralianAddress = BaseCDAModel.CreateAustralianAddress();

            var address2 = BaseCDAModel.CreateAddress();
            address2.AddressAbsentIndicator = AddressAbsentIndicator.NoFixedAddressIndicator;
            address2.AddressPurpose = AddressPurpose.TemporaryAccommodation;
            address2.AustralianAddress = BaseCDAModel.CreateAustralianAddress();

            var addressList = new List<IAddress> { address1, address2 };

            author.Participant.Addresses = addressList;

            // Document Author > Participant > Elec-tronic Communication Detail
            var coms1 = BaseCDAModel.CreateElectronicCommunicationDetail(
                "0345754566",
                ElectronicCommunicationMedium.Telephone,
                ElectronicCommunicationUsage.WorkPlace);
            var coms2 = BaseCDAModel.CreateElectronicCommunicationDetail(
                "authen@globalauthens.com",
                ElectronicCommunicationMedium.Email,
                ElectronicCommunicationUsage.WorkPlace);

            author.Participant.ElectronicCommunicationDetails = new List<ElectronicCommunicationDetail> { coms1, coms2 };

            // Document Author > Participant > Per-son or Organisation or Device > Person > Person Name
            var name1 = BaseCDAModel.CreatePersonName();
            name1.FamilyName = "Smith";

            var name2 = BaseCDAModel.CreatePersonName();
            name2.FamilyName = "Wong";
            name2.NameSuffix = new List<string> { "Sir" };

            person.PersonNames = new List<IPersonName>() { name1, name2 };

            // Document Author > Participant > Per-son or Organisation or Device > Person > Employment Detail
            person.Organisation = BaseCDAModel.CreateEmploymentOrganisation();
            person.Organisation.Identifiers = new List<Identifier> { 
                BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.HPIO, "8003620833333789"),
                BaseCDAModel.CreateIdentifier("SampleAuthority", null, null, "1.2.3.4.5.66666", null)
            };
            person.Organisation.Name = "Good Hospital";

            // Document Author > Participation Period
            author.AuthorParticipationPeriodOrDateTimeAuthored = new ISO8601DateTime(DateTime.Now, ISO8601DateTime.Precision.Minute);
                                    
            if (!mandatoryOnly)
            {               
                person.Organisation.Department = "Surgical Ward";
                person.Organisation.NameUsage = OrganisationNameUsage.LocallyUsedName;

                name1.GivenNames = new List<string> { "Good" };
                name1.Titles = new List<string> { "Doctor" };
                name1.NameUsages = new List<NameUsage> { NameUsage.Legal };

                name2.GivenNames = new List<string> { "Davey" };
                name2.Titles = new List<string> { "Brother" };
                name2.NameUsages = new List<NameUsage> { NameUsage.NewbornName };
                                
                address1.AustralianAddress.UnstructuredAddressLines = new List<string> { "1 Clinician Street" };
                address1.AustralianAddress.SuburbTownLocality = "Nehtaville";
                address1.AustralianAddress.State = AustralianState.QLD;
                address1.AustralianAddress.PostCode = "5555";
                address1.AustralianAddress.DeliveryPointId = 32568931;
                address1.AddressAbsentIndicator = null;

                address2.AustralianAddress.UnstructuredAddressLines = new List<string> { "2 Clinician Street" };
                address2.AustralianAddress.SuburbTownLocality = "Nehtaville";
                address2.AustralianAddress.State = AustralianState.QLD;
                address2.AustralianAddress.PostCode = "5555";
                address2.AustralianAddress.DeliveryPointId = 32568931;
                address2.AddressAbsentIndicator = null;
            }

            author.Participant.Person = person;                       
        }

        /// <summary>
        /// Creates and Hydrates a custodian
        /// 
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Custodian</returns>
        public static void HydrateCustodian(IParticipationCustodian participationCustodian, bool mandatoryOnly)
        {
            var custodian = BaseCDAModel.CreateParticipantCustodian();

            // custodian/assignedCustodian
            participationCustodian.Participant = custodian;

            // custodian/assignedCustodian/representedCustodianOrganization
            custodian.Organisation = BaseCDAModel.CreateOrganisationName();

            // custodian/assignedCustodian/representedCustodianOrganization/<Entity Identifier>
            custodian.Organisation.Identifiers = new List<Identifier> { 
                    BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.HPIO, "8003621231166540") 
                };

            // custodian/assignedCustodian/representedCustodianOrganization/name
            custodian.Organisation.Name = "Burrill Lake Medical Centre";

            if (!mandatoryOnly)
            {
                // custodian/assignedCustodian/representedCustodianOrganization/<Address>
                var address1 = BaseCDAModel.CreateAddress();
                address1.AddressPurpose = AddressPurpose.Residential;
                address1.AustralianAddress = BaseCDAModel.CreateAustralianAddress();
                address1.AustralianAddress.UnstructuredAddressLines = new List<string> { "1 Custodian Street" };
                address1.AustralianAddress.SuburbTownLocality = "Nehtaville";
                address1.AustralianAddress.State = AustralianState.QLD;
                address1.AustralianAddress.PostCode = "5555";
                address1.AustralianAddress.DeliveryPointId = 32568931;

                custodian.Address = address1;

                // custodian/assignedCustodian/representedCustodianOrganization/<Electronic Communication Detail>
                var coms1 = BaseCDAModel.CreateElectronicCommunicationDetail(
                    "0345754566",
                    ElectronicCommunicationMedium.Telephone,
                    ElectronicCommunicationUsage.WorkPlace);
                custodian.ElectronicCommunicationDetail = coms1;
            }
        }

        /// <summary>
        /// Creates and Hydrates a list of recipients
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated list of recipients</returns>
        public static void HydrateRecipient(IParticipationInformationRecipient recipient, RecipientType recipientType, bool mandatoryOnly)
        {
            recipient.Participant = BaseCDAModel.CreateParticipantForInformationRecipient();

            // informationRecipient/@typeCode
            recipient.Participant.RecipientType = recipientType;

            // informationRecipient/intendedRecipient
            recipient.Participant.Person = BaseCDAModel.CreatePerson();

            if (!mandatoryOnly)
            {
                // informationRecipient/intendedRecipient/informationRecipient/<Entity Identifier>
                recipient.Participant.Person.Identifiers = new List<Identifier> { 
                    BaseCDAModel.CreateIdentifier("SampleAuthority", null, null, "1.2.3.4.5.6677", null),
                    BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.HPII, "8003614444567893") 
                };

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

                var address2 = BaseCDAModel.CreateAddress();
                address2.AddressPurpose = AddressPurpose.TemporaryAccommodation;
                address2.InternationalAddress = BaseCDAModel.CreateInternationalAddress();
                address2.InternationalAddress.AddressLine = new List<string> { "1 Overseas Street" };
                address2.InternationalAddress.Country = Country.Albania;
                address2.InternationalAddress.PostCode = "12345";
                address2.InternationalAddress.StateProvince = "Foreign Land";

                var addressList = new List<IAddress> { address1, address2 };

                recipient.Participant.Addresses = addressList;

                // informationRecipient/intendedRecipient/<Electronic Communication Detail>
                var coms1 = BaseCDAModel.CreateElectronicCommunicationDetail(
                    "0345754566",
                    ElectronicCommunicationMedium.Telephone,
                    ElectronicCommunicationUsage.WorkPlace);

                var coms2 = BaseCDAModel.CreateElectronicCommunicationDetail(
                    "authen@globalauthens.com",
                    ElectronicCommunicationMedium.Email,
                    ElectronicCommunicationUsage.WorkPlace);

                recipient.Participant.ElectronicCommunicationDetails = new List<ElectronicCommunicationDetail> { coms1, coms2 };

                // informationRecipient/intendedRecipient/informationRecipient/<Person Name>

                var name1 = BaseCDAModel.CreatePersonName();
                name1.GivenNames = new List<string> { "Information" };
                name1.FamilyName = "Recipient";
                name1.Titles = new List<string> { "Doctor" };
                name1.NameUsages = new List<NameUsage> { NameUsage.Legal };

                var name2 = BaseCDAModel.CreatePersonName();
                name2.GivenNames = new List<string> { "Information" };
                name2.FamilyName = "Recipient";
                name2.Titles = new List<string> { "Mr" };
                name2.NameUsages = new List<NameUsage> { NameUsage.NewbornName };

                recipient.Participant.Person.PersonNames = new List<IPersonName> { name1, name2 };

                // informationRecipient/intendedRecipient/receivedOrganization
                recipient.Participant.Organisation = BaseCDAModel.CreateOrganisationName();

                // informationRecipient/intendedRecipient/receivedOrganization/name
                recipient.Participant.Organisation.Name = "Specialist Clinics";

                recipient.Participant.Organisation.Identifiers = new List<Identifier> { 
                    BaseCDAModel.CreateIdentifier("SampleAuthority", null, null, "1.2.3.4.5.6677", null),
                    BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.HPIO, "8003621231167886") 
                };
            }
        }

        /// <summary>
        /// Creates and Hydrates an Authenticator
        /// Note: the data used within this method is intended as a guide and should be replaced.
        /// </summary>
        /// <returns>A Hydrated authenticator</returns>
        public static void HydrateAuthenticator(IParticipationLegalAuthenticator authenticator, bool mandatoryOnly)
        {
            // LegalAuthenticator/assignedEntity
            authenticator.Participant = BaseCDAModel.CreateParticipantForLegalAuthenticator();

            // LegalAuthenticator/time/@value
            authenticator.Participant.DateTimeAuthenticated = new ISO8601DateTime(DateTime.Now, ISO8601DateTime.Precision.Minute);

            // LegalAuthenticator/assignedEntity/assignedPerson
            authenticator.Participant.Person = BaseCDAModel.CreatePerson();

            var loacalAuthorityCode = BaseCDAModel.CreateCodableText("EI", CodingSystem.HL7IdentifierType, null, null, null);

            // LegalAuthenticator/assignedEntity/<Entity Identifier>
            authenticator.Participant.Person.Identifiers = new List<Identifier> 
                { 
                  BaseCDAModel.CreateIdentifier("LoacalAuthority", null, null, "1.2.3.4.5.66666", loacalAuthorityCode), 
                  BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.HPII, "8003615833334118") 
                };

            //LegalAuthenticator/assignedEntity/assignedPerson/<Person Name>
            var name1 = BaseCDAModel.CreatePersonName();
            name1.GivenNames = new List<string> { "Good" };
            name1.FamilyName = "Doctor";
            name1.Titles = new List<string> { "Doctor" };
            name1.NameUsages = new List<NameUsage> { NameUsage.Legal };

            authenticator.Participant.Person.PersonNames = new List<IPersonName> { name1 };

            if (!mandatoryOnly)
            {
                // LegalAuthenticator/assignedEntity/code
                authenticator.Role = BaseCDAModel.CreateRole(Occupation.GeneralMedicalPractitioner);

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

                var address2 = BaseCDAModel.CreateAddress();
                address2.AddressPurpose = AddressPurpose.TemporaryAccommodation;
                address2.InternationalAddress = BaseCDAModel.CreateInternationalAddress();
                address2.InternationalAddress.AddressLine = new List<string> { "1 Overseas Street" };
                address2.InternationalAddress.Country = Country.Albania;
                address2.InternationalAddress.PostCode = "12345";
                address2.InternationalAddress.StateProvince = "Foreign Land";

                var addressList = new List<IAddress> { address1, address2 };

                authenticator.Participant.Addresses = addressList;

                // LegalAuthenticator/assignedEntity/<Electronic Communication Detail>
                var coms1 = BaseCDAModel.CreateElectronicCommunicationDetail(
                    "0345754566",
                    ElectronicCommunicationMedium.Telephone,
                    ElectronicCommunicationUsage.WorkPlace);
                var coms2 = BaseCDAModel.CreateElectronicCommunicationDetail(
                    "authen@globalauthens.com",
                    ElectronicCommunicationMedium.Email,
                    ElectronicCommunicationUsage.WorkPlace);
                authenticator.Participant.ElectronicCommunicationDetails = new List<ElectronicCommunicationDetail> { coms1, coms2 };

                // LegalAuthenticator/assignedEntity/representedOrganization
                authenticator.Participant.Organisation = BaseCDAModel.CreateOrganisationName();

                // LegalAuthenticator/assignedEntity/representedOrganization/name
                authenticator.Participant.Organisation.Name = "Oz Health Clinic";

                // LegalAuthenticator/assignedEntity/representedOrganization/<Entity Identifier>
                authenticator.Participant.Organisation.Identifiers = new List<Identifier> 
                { 
                    BaseCDAModel.CreateIdentifier("SampleAuthority", null, null, "1.2.3.4.55555", null),
                    BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.HPIO, "8003620000001144") 
                };
            }
            
        }

        #region Diagnostic Investigations Sections

        /// <summary>
        /// Creates and hydrates the 'Other Test Result' Attachment section.
        /// </summary>
        /// <returns>A hydrated 'OtherTestResult' object.</returns>
        public static OtherTestResult CreateOtherTestResultAttachment()
        {
          var otherTestResult = BaseCDAModel.CreateOtherTestResult();
          otherTestResult.ReportName = BaseCDAModel.CreateCodableText(null, null, null, "Report with Attachment", null);
          otherTestResult.ReportStatus = ResultStatus.Interim;

          // Report ExternalData
          ExternalData report = BaseCDAModel.CreateExternalData();
          report.ExternalDataMediaType = MediaType.PDF;
          report.Path = ResultFileNameAndPath;
          report.Caption = "Path File";

          otherTestResult.ReportContent = BaseCDAModel.CreateEncapsulatedData();
          otherTestResult.ReportContent.ExternalData = report;
          otherTestResult.ReportDate = new ISO8601DateTime(DateTime.Now.AddDays(-2));

          return otherTestResult;
        }

        /// <summary>
        /// Creates and hydrates the 'Other Test Result' text only section.
        /// </summary>
        /// <returns>A hydrated 'OtherTestResult' object.</returns>
        public static OtherTestResult CreateOtherTestResultText()
        {
          var otherTestResult = BaseCDAModel.CreateOtherTestResult();
          otherTestResult.ReportName = BaseCDAModel.CreateCodableText(null, null, null, "Report with Text", null);
          otherTestResult.ReportStatus = ResultStatus.Interim;

          otherTestResult.ReportContent = BaseCDAModel.CreateEncapsulatedData();
          otherTestResult.ReportContent.Text = "Report Content Text";
          otherTestResult.ReportDate = new ISO8601DateTime(DateTime.Now.AddDays(-2));

          return otherTestResult;
        }

        public static PathologyTestResult CreatePathologyResults(string name, string simpleNarrativePath)
        {
          // Pathology test result
          var pathologyTestResult = EDischargeSummary.CreatePathologyTestResult();

          if (!simpleNarrativePath.IsNullOrEmptyWhitespace()) pathologyTestResult.xPreNarrative = File.ReadAllText(simpleNarrativePath);

          pathologyTestResult.TestResultDateTime = new ISO8601DateTime(DateTime.Now.AddDays(-2));
          pathologyTestResult.OverallTestResultStatus = ResultStatus.Final;

          var specimenDetail = EDischargeSummary.CreateSpecimenDetail();
          specimenDetail.CollectionDateTime = new ISO8601DateTime(DateTime.Now.AddDays(-2));

          pathologyTestResult.PathologyTestSpecimenDetail = new List<SpecimenDetail> { specimenDetail };

          pathologyTestResult.TestResultName = EDischargeSummary.CreateCodableText("18719-5", CodingSystem.LOINC, name, null, null);

          return pathologyTestResult;
        }


        /// <summary>
        /// Creates and hydrates the 'Pathology Test Results' section.
        /// </summary>
        /// <param name="name">Name of the pathology test result.</param>
        /// <returns>A hydrated 'PathologyTestResult' object.</returns>
        public static PathologyTestResult CreatePathologyResults(string name)
        {
          // Pathology test result
          PathologyTestResult pathologyTestResult = EDischargeSummary.CreatePathologyTestResult();

          // Image 1
          ExternalData anatomicalSiteImage = EDischargeSummary.CreateExternalData();
          anatomicalSiteImage.ExternalDataMediaType = MediaType.JPEG;
          anatomicalSiteImage.Path = ImageFileNameAndPath;
          anatomicalSiteImage.Caption = "AnatomicalSite X-Ray";

          // Image 1
          ExternalData physicalDetailsImage = EDischargeSummary.CreateExternalData();
          physicalDetailsImage.ExternalDataMediaType = MediaType.JPEG;
          physicalDetailsImage.Path = ImageFileNameAndPath;
          physicalDetailsImage.Caption = "physicalDetailsImage X-Ray";

          // Report 1
          ExternalData report1 = EDischargeSummary.CreateExternalData();
          report1.ExternalDataMediaType = MediaType.PDF;
          report1.Path = ResultFileNameAndPath;
          report1.Caption = "Results";

          // Anatomical site 1
          AnatomicalSite anatomicalSite1 = CreateAnatomicalSite(
              "Arm",
              "47787007",
              CodingSystem.SNOMED,
              "Dacryocyte",
              "7771000",
              "Left",
              new List<ExternalData> { anatomicalSiteImage }
              );

          // Anatomical site 2
          AnatomicalSite anatomicalSite2 = CreateAnatomicalSite(
              "Arm",
              "129124008",
              CodingSystem.SNOMED,
              "Sterile abscess",
              "419161000",
              "Unilateral left",
              null
              );


          // Anatomical site 3
          AnatomicalSite anatomicalSite3 = CreateAnatomicalSite(
              "Arm",
              "51204001",
              CodingSystem.SNOMED,
              "Zygomatic arch structure",
              "24028007",
              "Right",
              null
              );

          // Specimen detail 1
          SpecimenDetail specimenDetail1 = EDischargeSummary.CreateSpecimenDetail();
          specimenDetail1.AnatomicalSite = new List<AnatomicalSite>
                                                 {
                                                     anatomicalSite1
                                                 };

          specimenDetail1.CollectionDateTime = new ISO8601DateTime(DateTime.Now.AddDays(-22));
          specimenDetail1.CollectionProcedure = EDischargeSummary.CreateCollectionProcedure("82078001", CodingSystem.SNOMED, "blood draw", null, null);
          specimenDetail1.CollectionSetting = "Ward 1A";
          specimenDetail1.ContainerIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.36.45364", "CNH45218964");
          specimenDetail1.ParentSpecimenIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.36.45364", EDischargeSummary.CreateGuid());
          specimenDetail1.SpecimenDescription = "physicalDetails-Description";
          specimenDetail1.PhysicalDetails = new List<PhysicalDetails> { BaseCDAModel.CreatePhysicalDetails("6", "ml", physicalDetailsImage) };
          specimenDetail1.ReceivedDateTime = new ISO8601DateTime(DateTime.Now);
          specimenDetail1.SamplingPreconditions = EDischargeSummary.CreateSamplingPreconditions("16985007", CodingSystem.SNOMED, "fasting", null, null);
          specimenDetail1.SpecimenIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.36.45364", EDischargeSummary.CreateGuid());
          specimenDetail1.SpecimenTissueType = EDischargeSummary.CreateSpecimenTissueType("85756007", CodingSystem.SNOMED, "Tissue", null, null);


          // Image 1
          ExternalData physicalDetailsImage1 = EDischargeSummary.CreateExternalData();
          physicalDetailsImage1.ExternalDataMediaType = MediaType.JPEG;
          physicalDetailsImage1.Path = ImageFileNameAndPath;
          physicalDetailsImage1.Caption = "PhysicalDetails 1";

          // Image 1
          ExternalData physicalDetailsImage2 = EDischargeSummary.CreateExternalData();
          physicalDetailsImage2.ExternalDataMediaType = MediaType.JPEG;
          physicalDetailsImage2.Path = ImageFileNameAndPath;
          physicalDetailsImage2.Caption = "PhysicalDetails 2";

          // Image 1
          ExternalData physicalDetailsImage3 = EDischargeSummary.CreateExternalData();
          physicalDetailsImage3.ExternalDataMediaType = MediaType.JPEG;
          physicalDetailsImage3.Path = ImageFileNameAndPath;
          physicalDetailsImage3.Caption = "PhysicalDetails 3";

          // Specimen detail 2
          SpecimenDetail specimenDetail2 = EDischargeSummary.CreateSpecimenDetail();
          specimenDetail2.AnatomicalSite = new List<AnatomicalSite>
                                                 {
                                                     anatomicalSite2
                                                 };

          specimenDetail2.CollectionDateTime = new ISO8601DateTime(DateTime.Now.AddDays(-12));
          specimenDetail2.CollectionProcedure = EDischargeSummary.CreateCollectionProcedure("122575003", CodingSystem.SNOMED, "Urine sample", null, null);
          specimenDetail2.CollectionSetting = "Ward 3B";
          specimenDetail2.ContainerIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.36.45364", "AZH45218964");
          specimenDetail2.ParentSpecimenIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.36.45364", EDischargeSummary.CreateGuid());
          specimenDetail2.SpecimenDescription = "Urine sample";
          specimenDetail2.PhysicalDetails = new List<PhysicalDetails> { BaseCDAModel.CreatePhysicalDetails("20", "kg", physicalDetailsImage1) };
          specimenDetail2.ReceivedDateTime = new ISO8601DateTime(DateTime.Now);
          specimenDetail2.SamplingPreconditions = EDischargeSummary.CreateSamplingPreconditions("16985007", CodingSystem.SNOMED, "fasting", null, null);
          specimenDetail2.SpecimenIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.36.45364", EDischargeSummary.CreateGuid());

          // Specimen detail 3
          SpecimenDetail specimenDetail3 = EDischargeSummary.CreateSpecimenDetail();
          specimenDetail3.CollectionDateTime = new ISO8601DateTime(DateTime.Now.AddDays(-12));
          specimenDetail3.CollectionProcedure = EDischargeSummary.CreateCollectionProcedure("122575003", CodingSystem.SNOMED, "Urine sample", null, null);
          specimenDetail3.CollectionSetting = "Ward 3B";
          specimenDetail3.ContainerIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.36.45364", "AZH45218964");
          specimenDetail3.ParentSpecimenIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.36.45364", EDischargeSummary.CreateGuid());
          specimenDetail3.SpecimenDescription = "Urine sample";
          specimenDetail3.PhysicalDetails = new List<PhysicalDetails> { BaseCDAModel.CreatePhysicalDetails("20", "kg", physicalDetailsImage3) };
          specimenDetail3.ReceivedDateTime = new ISO8601DateTime(DateTime.Now);
          specimenDetail3.SamplingPreconditions = EDischargeSummary.CreateSamplingPreconditions("16985007", CodingSystem.SNOMED, "fasting", null, null);
          specimenDetail3.SpecimenIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.36.45364", EDischargeSummary.CreateGuid());

          specimenDetail3.AnatomicalSite = new List<AnatomicalSite>
                                                 {
                                                     anatomicalSite3
                                                 };
          // Test result 1
          ITestResult testResult1 = EDischargeSummary.CreateTestResult();
          testResult1.Comments = new List<string> { "Sodium test result comments", "More comments", "Another comment" };
          testResult1.ReferenceRangeGuidance = "Reference range guidance comments for Sodium; eg. the quantity should be between the high and low values";
          testResult1.ResultName = EDischargeSummary.CreateResultName("39972003", CodingSystem.SNOMED, "Sodium", null, null);
          testResult1.ResultStatus = ResultStatus.Interim;
          testResult1.ResultValue = EDischargeSummary.CreateResultValue();
          testResult1.ResultValue.ValueAsQuantity = EDischargeSummary.CreateQuantity();
          testResult1.ResultValue.ValueAsQuantity.Value = "12.88";
          testResult1.ResultValue.ValueAsQuantity.Units = "ml";
          testResult1.ResultValueStatus = HL7ObservationInterpretationNormality.Normal;
          testResult1.ResultValueReferenceRangeDetails = new List<ResultValueReferenceRangeDetail>
                                                               {
                                                                   CreateReferenceRange("75540009", "High", "ml", 50, 100), 
                                                                   CreateReferenceRange("62482003", "Low", "ml", 10, 20), 
                                                               };
          // Test result 2
          ITestResult testResult2 = EDischargeSummary.CreateTestResult();
          testResult2.Comments = new List<string> { "Blood test result comments", "More comments", "Another comment" };
          testResult2.ReferenceRangeGuidance = "Reference range guidance comments for blood; eg. the quantity should be between the high and low values";
          testResult2.ResultName = EDischargeSummary.CreateResultName("87612001", CodingSystem.SNOMED, "Blood", null, null);
          testResult2.ResultStatus = ResultStatus.Final;
          testResult2.ResultValue = EDischargeSummary.CreateResultValue();
          testResult2.ResultValue.ValueAsQuantity = EDischargeSummary.CreateQuantity();
          testResult2.ResultValue.ValueAsQuantity.Value = "5";
          testResult2.ResultValue.ValueAsQuantity.Units = "km";
          testResult2.ResultValueStatus = HL7ObservationInterpretationNormality.Normal;
          testResult2.ResultValueReferenceRangeDetails = new List<ResultValueReferenceRangeDetail>
                                                               {
                                                                   CreateReferenceRange("75540009", "High", "ml", 50, 100), 
                                                                   CreateReferenceRange("62482003", "Low", "ml", 10, 20), 
                                                               };

          // Test result 3
          ITestResult testResult3 = EDischargeSummary.CreateTestResult();
          testResult3.Comments = new List<string> { "Heart test result comments", "More comments", "Another comment" };
          testResult3.ReferenceRangeGuidance = "Reference range guidance comments for heart; eg. the quantity should be between the high and low values";
          testResult3.ResultName = EDischargeSummary.CreateResultName("87612001", CodingSystem.SNOMED, "Blood", null, null);
          testResult3.ResultStatus = ResultStatus.Final;
          testResult3.ResultValue = EDischargeSummary.CreateResultValue();
          testResult3.ResultValue.ValueAsQuantity = EDischargeSummary.CreateQuantity();
          testResult3.ResultValue.ValueAsQuantity.Value = "5";
          testResult3.ResultValue.ValueAsQuantity.Units = "km";
          testResult3.ResultValueStatus = HL7ObservationInterpretationNormality.Normal;
          testResult3.ResultValueReferenceRangeDetails = new List<ResultValueReferenceRangeDetail>
                                                               {
                                                                   CreateReferenceRange("75540009", "High", "psi", 2, 150), 
                                                                   CreateReferenceRange("62482003", "Low", "psi", 15, 200), 
                                                               };


          // Test request 1
          ITestRequest testRequest1 = EDischargeSummary.CreateTestRequest();
          testRequest1.LaboratoryTestResultIdentifier = BaseCDAModel.CreateInstanceIdentifier(BaseCDAModel.CreateGuid(), "Laboratory Test Result Identifier");
          testRequest1.TestsRequested = new List<ICodableText>
                                              {
                                                  EDischargeSummary.CreateTestRequestName("67922002", CodingSystem.SNOMED, "Serum"),
                                                  EDischargeSummary.CreateTestRequestName("75367002", CodingSystem.SNOMED, "Blood pressure"),
                                              };

          // Test request 2
          ITestRequest testRequest2 = EDischargeSummary.CreateTestRequest();
          testRequest2.LaboratoryTestResultIdentifier = BaseCDAModel.CreateInstanceIdentifier(BaseCDAModel.CreateGuid(), "Laboratory Test Result Identifier");
          testRequest2.TestsRequested = new List<ICodableText>
                                              {
                                                  EDischargeSummary.CreateTestRequestName("302509004", CodingSystem.SNOMED, "Heart"),
                                                  EDischargeSummary.CreateTestRequestName("302509004", CodingSystem.SNOMED, "Heart"),
                                              };

          // Test result group 1
          ITestResultGroup testResultGroup1 = EDischargeSummary.CreateTestResultGroup();
          testResultGroup1.Results = new List<ITestResult> { testResult1, testResult2 };
          testResultGroup1.ResultGroupSpecimenDetail = specimenDetail1;
          testResultGroup1.ResultGroupName = EDischargeSummary.CreateResultGroupName
              (
                  "18719-5",
                  CodingSystem.LOINC,
                  "Chemistry Studies (Set)",
                  null,
                  null
              );

          // Test result group 2
          ITestResultGroup testResultGroup2 = EDischargeSummary.CreateTestResultGroup();
          testResultGroup2.Results = new List<ITestResult> { testResult3 };
          testResultGroup2.ResultGroupSpecimenDetail = specimenDetail2;
          testResultGroup2.ResultGroupName = EDischargeSummary.CreateResultGroupName(NullFlavour.PositiveInfinity);

          pathologyTestResult.Comment = "testResultGroup-Comment";
          pathologyTestResult.Conclusion = "testResultGroup-Conclusion";
          pathologyTestResult.TestResultDateTime = new ISO8601DateTime(DateTime.Now.AddDays(-2));
          pathologyTestResult.PathologicalDiagnosis = new List<ICodableText>
                                                            {
                                                                EDischargeSummary.CreatePathologicalDiagnois("17621005", CodingSystem.SNOMED, "Normal", null, null),
                                                                EDischargeSummary.CreatePathologicalDiagnois("85531003", CodingSystem.SNOMED, "Abnormal", null, null)
                                                            };
          pathologyTestResult.OverallTestResultStatus = ResultStatus.Final;
          pathologyTestResult.ClinicalInformationProvided = "Hepatitus";
          pathologyTestResult.DiagnosticService = DiagnosticServiceSectionID.Chemistry;
          pathologyTestResult.TestRequestDetails = new List<ITestRequest>
                                                         {
                                                             testRequest1, testRequest2
                                                         };

          pathologyTestResult.PathologyTestResultGroup = new List<ITestResultGroup>()
                                                           {
                                                            testResultGroup1, testResultGroup2
                                                           };

          pathologyTestResult.PathologyTestSpecimenDetail = new List<SpecimenDetail> { specimenDetail3 };
          pathologyTestResult.TestResultName = EDischargeSummary.CreateCodableText("18719-5", CodingSystem.LOINC, name, null, null);
          pathologyTestResult.TestResultRepresentation = BaseCDAModel.CreateEncapsulatedData();
          pathologyTestResult.TestResultRepresentation.Text = "Lipase 150 U/L (RR < 70)";

          return pathologyTestResult;
        }

        /// <summary>
        /// Creates and hydrates the 'Imaging Examination Results' section.
        /// </summary>
        /// <param name="name">Name of the imaging examination results.</param>
        /// <returns>A hydrated 'IImagingExaminationResult' object.</returns>
        public static IImagingExaminationResult CreateImagingResults(string name)
        {
          // Image 1
          ExternalData image1 = EDischargeSummary.CreateExternalData();
          image1.ExternalDataMediaType = MediaType.JPEG;
          image1.Path = ImageFileNameAndPath;
          image1.Caption = "X-Ray";

          // Image 2
          ExternalData image2 = EDischargeSummary.CreateExternalData();
          image2.ExternalDataMediaType = MediaType.JPEG;
          image2.Path = ImageFileNameAndPath;
          image2.Caption = "X-Ray - Left Femur";

          // Image 3
          ExternalData image3 = EDischargeSummary.CreateExternalData();
          image3.ExternalDataMediaType = MediaType.JPEG;
          image3.Path = ImageFileNameAndPath;
          image3.Caption = "X-Ray - Right Arm";

          // Anatomical site 1
          ICodableText nameOfLocation = BaseCDAModel.CreateCodableText("88738008", CodingSystem.SNOMED, "Subcutaneous tissue structure of lateral surface of index finger", null, null);
          ICodableText side = BaseCDAModel.CreateCodableText("7771000", CodingSystem.SNOMED, "Left", null, null);

          AnatomicalSite anatomicalSite1 = CreateAnatomicalSite(
              "Femur Length",
              nameOfLocation,
              side,
              new List<ExternalData> { image1, image2 }
              );

          // Anatomical site 2
          AnatomicalSite anatomicalSite2 = CreateAnatomicalSite(
              "Arm",
              "88738008",
              CodingSystem.SNOMED,
              "Subcutaneous tissue structure of lateral surface of index finger",
              "24028007",
              "Right",
              new List<ExternalData> { image3 }
              );

          // Imaging results 1
          IImagingResult imagingResult1 = EDischargeSummary.CreateImagingResult();
          imagingResult1.Comments = new List<string> { "Femur measured during ultrasound scan.", "Legs measured during ultrasound scan." };
          imagingResult1.ResultName = EDischargeSummary.CreateResultName("16310003", CodingSystem.SNOMED, "ultrasound scan", null, null);
          imagingResult1.ResultValue = EDischargeSummary.CreateResultValue();
          imagingResult1.ResultValue.ValueAsCodableText = EDischargeSummary.CreateCodableText("371573008", CodingSystem.SNOMED, "Ultrasound", null, null);
          imagingResult1.ResultValueStatus = HL7ObservationInterpretationNormality.Normal;
          imagingResult1.ResultValueReferenceRangeDetails = new List<ResultValueReferenceRangeDetail>
                                                                  {
                                                                      CreateReferenceRange("260395002", "Normal range", "ml", 17, 13), 
                                                                      CreateReferenceRange("75540009", "High", "ml", 50, 100)
                                                                  };

          // Imaging results 2
          IImagingResult imagingResult2 = EDischargeSummary.CreateImagingResult();
          imagingResult2.Comments = new List<string> { "Neck measured during ultrasound scan.", "Neck measured during ultrasound scan." };
          imagingResult2.ResultName = EDischargeSummary.CreateResultName("16310040", CodingSystem.SNOMED, "neck ultrasound scan", null, null);
          imagingResult2.ResultValue = EDischargeSummary.CreateResultValue();
          imagingResult2.ResultValue.ValueAsCodableText = EDischargeSummary.CreateCodableText("77777", CodingSystem.SNOMED, "x-ray description", null, null);
          imagingResult2.ResultValueStatus = HL7ObservationInterpretationNormality.Normal;
          imagingResult2.ResultValueReferenceRangeDetails = new List<ResultValueReferenceRangeDetail>
                                                                  {
                                                                      CreateReferenceRange("260395002", "Normal range", "kg", 15, 18), 
                                                                      CreateReferenceRange("75540009", "High", "kg", 60, 110)
                                                                  };

          // Imaging results 3
          IImagingResult imagingResult3 = EDischargeSummary.CreateImagingResult();
          imagingResult3.Comments = new List<string> { "Waist measured during ultrasound scan.", "Waist measured during ultrasound scan." };
          imagingResult3.ResultName = EDischargeSummary.CreateResultName("371573008", CodingSystem.SNOMED, "Ultrasound", null, null);
          imagingResult3.ResultValue = EDischargeSummary.CreateResultValue();
          imagingResult3.ResultValue.ValueAsCodableText = EDischargeSummary.CreateCodableText("371573008", CodingSystem.SNOMED, "Ultrasound", null, null);
          imagingResult3.ResultValueStatus = HL7ObservationInterpretationNormality.Normal;
          imagingResult3.ResultValueReferenceRangeDetails = new List<ResultValueReferenceRangeDetail>
                                                                  {
                                                                      CreateReferenceRange("260395002", "Normal range", "ml", 15, 18), 
                                                                      CreateReferenceRange("75540009", "High", "ml", 60, 110)
                                                                  };

          // Image 4
          ExternalData image4 = EDischargeSummary.CreateExternalData();
          image4.ExternalDataMediaType = MediaType.JPEG;
          image4.Path = ImageFileNameAndPath;
          image4.Caption = "4 X-Ray";

          // Image details 1
          IImageDetails imageDetails1 = EDischargeSummary.CreateImageDetails();
          imageDetails1.DateTime = new ISO8601DateTime(DateTime.Now);
          imageDetails1.ImageIdentifier = BaseCDAModel.CreateInstanceIdentifier(BaseCDAModel.CreateGuid(), "Image Identifer");
          imageDetails1.SeriesIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.3.1.2.2654654654654564", "Series Identifier");
          imageDetails1.SubjectPosition = "Supine";

          imageDetails1.Image = image4;

          // Image 5
          ExternalData image5 = EDischargeSummary.CreateExternalData();
          image5.ExternalDataMediaType = MediaType.JPEG;
          image5.Path = ImageFileNameAndPath;
          image5.Caption = "5 X-Ray";

          // Image details 2
          IImageDetails imageDetails2 = EDischargeSummary.CreateImageDetails();
          imageDetails2.DateTime = new ISO8601DateTime(DateTime.Now);
          imageDetails2.SubjectPosition = "Sublime";
          imageDetails2.SeriesIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.3.1.2.2654654654654564", "Series Identifier");
          imageDetails2.Image = image5;

          // Image 6
          ExternalData image6 = EDischargeSummary.CreateExternalData();
          image6.ExternalDataMediaType = MediaType.JPEG;
          image6.Path = ImageFileNameAndPath;
          image6.Caption = "6 X-Ray";

          // Image details 3
          IImageDetails imageDetails3 = EDischargeSummary.CreateImageDetails();
          imageDetails3.DateTime = new ISO8601DateTime(DateTime.Now);
          imageDetails3.SubjectPosition = "Head";
          imageDetails3.SeriesIdentifier = BaseCDAModel.CreateInstanceIdentifier("1.2.3.1.2.2654654654654564", "Series Identifier");
          imageDetails3.Image = image6;

          // Imaging result group 1
          IImagingResultGroup imagingResultGroup1 = EDischargeSummary.CreateImagingResultGroup();
          imagingResultGroup1.Results = new List<IImagingResult>
                                              {
                                                  imagingResult1 
                                              };
          imagingResultGroup1.AnatomicalSite = anatomicalSite1;
          imagingResultGroup1.ResultGroupName = EDischargeSummary.CreateResultGroupName
              (
                  "268445003",
                  CodingSystem.SNOMED,
                  "ultrasound scan - obstetric",
                  null,
                  null
              );

          // Imaging result group 2
          IImagingResultGroup imagingResultGroup2 = EDischargeSummary.CreateImagingResultGroup();
          imagingResultGroup2.Results = new List<IImagingResult>
                                              {
                                                  imagingResult3
                                              };
          imagingResultGroup2.AnatomicalSite = anatomicalSite2;
          imagingResultGroup2.ResultGroupName = EDischargeSummary.CreateResultGroupName
              (
                  "371573008",
                  CodingSystem.SNOMED,
                  "Ultrasound",
                  null,
                  null
              );

          // Imaging examination result 1
          IImagingExaminationResult imagingExaminationResult = EDischargeSummary.CreateImagingExaminationResult();
          imagingExaminationResult.ClinicalInformationProvided = "Patient pregnant. Confirm dates. Estimate from LNMP 18 weeks.";
          imagingExaminationResult.ExaminationRequestDetails = new List<IImagingExaminationRequest>
                                                                     {
                                                                         CreateImagingExaminationRequest("A/U Obstetric - Dating", imageDetails1),
                                                                         CreateImagingExaminationRequest("A/U Skin - Stuff", new List<IImageDetails> { imageDetails2, imageDetails3 })
                                                                     };

          imagingExaminationResult.ExaminationResultName = EDischargeSummary.CreateExaminationResultName("1234", CodingSystem.METEOR, name, name, null);
          imagingExaminationResult.Findings = "Normal obstetric ultrasound with foetal biometry indicating getational age of 18W0D.";
          imagingExaminationResult.Modality = EDischargeSummary.CreateModality("371573008", CodingSystem.SNOMED, "Ultrasound", null, null);
          imagingExaminationResult.ResultDateTime = new ISO8601DateTime(DateTime.Now.AddDays(-2));
          imagingExaminationResult.ExaminationResultStatus = ResultStatus.Final;
          imagingExaminationResult.ExaminationResultRepresentation = "ResultRepresentation";

          imagingExaminationResult.ResultGroup = new List<IImagingResultGroup>
                                                       {
                                                           imagingResultGroup1, imagingResultGroup2
                                                       };

          return imagingExaminationResult;
        }

        /// Creates and Hydrates an natomicalSite
        /// </summary>
        /// <returns>AnatomicalSite</returns>
        private static AnatomicalSite CreateAnatomicalSite(String description, ICodableText nameOfLocation, ICodableText side, List<ExternalData> images)
        {
          var anatomicalSite = EReferral.CreateAnatomicalSite();
          anatomicalSite.Description = description;
          anatomicalSite.AnatomicalLocation = EReferral.CreateAnatomicalLocation();
          anatomicalSite.AnatomicalLocation.NameOfLocation = nameOfLocation;
          anatomicalSite.AnatomicalLocation.Side = side;
          anatomicalSite.Images = images;
          return anatomicalSite;
        }

        /// <summary>
        /// Creates and Hydrates an natomicalSite
        /// </summary>
        /// <returns>AnatomicalSite</returns>
        private static AnatomicalSite CreateAnatomicalSite(String description, String code, CodingSystem codingSystem, String name, String locationSideCode, String locationSide, List<ExternalData> images)
        {
          var anatomicalSite = EDischargeSummary.CreateAnatomicalSite();
          anatomicalSite.Description = description;
          anatomicalSite.AnatomicalLocation = EDischargeSummary.CreateAnatomicalLocation();
          anatomicalSite.AnatomicalLocation.NameOfLocation = EDischargeSummary.CreateAnatomicLocationName(code, codingSystem, name, null);
          anatomicalSite.AnatomicalLocation.Side = EDischargeSummary.CreateAnatomicLocationSide(locationSideCode, CodingSystem.SNOMED, locationSide, null, null);
          anatomicalSite.Images = images;
          return anatomicalSite;
        }

        /// <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 = EDischargeSummary.CreateResultValueReferenceRangeDetail();
          resultValueReferenceRangeDetail.Range = EDischargeSummary.CreateQuantityRange();
          resultValueReferenceRangeDetail.Range.High = high;
          resultValueReferenceRangeDetail.Range.Low = low;
          resultValueReferenceRangeDetail.Range.Units = units;
          resultValueReferenceRangeDetail.ResultValueReferenceRangeMeaning = EDischargeSummary.CreateResultValueReferenceRangeMeaning
                                                                              (
                                                                                  code,
                                                                                  CodingSystem.SNOMED,
                                                                                  name,
                                                                                  null,
                                                                                  null
                                                                              );

          return resultValueReferenceRangeDetail;
        }

        /// <summary>
        /// Creates and hydrates a 'IImagingExaminationRequest' object.
        /// </summary>
        /// <param name="examinationRequestName">Name of the examination request.</param>
        /// <param name="imageDetails">Image details.</param>
        /// <returns>A hydrated 'IImagingExaminationRequest' object</returns>
        private static IImagingExaminationRequest CreateImagingExaminationRequest(String examinationRequestName, IImageDetails imageDetails)
        {
          return CreateImagingExaminationRequest(examinationRequestName, new List<IImageDetails> { imageDetails });
        }


        /// <summary>
        /// Creates and hydrates an 'IImagingExaminationRequest' object.
        /// </summary>
        /// <param name="examinationRequestName">Name of the examination request.</param>
        /// <param name="imageDetails">List of 'ImageDetails'.</param>
        /// <returns>A hydrated 'IImagingExaminationRequest' object.</returns>
        private static IImagingExaminationRequest CreateImagingExaminationRequest(string examinationRequestName, List<IImageDetails> imageDetails)
        {
          var imagingExaminationRequest = EDischargeSummary.CreateImagingExaminationRequest();
          imagingExaminationRequest.ExaminationRequestedName = new List<String>
                                                                     {
                                                                         examinationRequestName, "another name"
                                                                     };
          imagingExaminationRequest.ReportIdentifier = BaseCDAModel.CreateInstanceIdentifier(BaseCDAModel.CreateGuid(), "3355552BHU-23.3");

          if (imageDetails != null && imageDetails.Any())
          {
            int index = 1;
            foreach (IImageDetails imageDetail in imageDetails)
            {
              imageDetail.ImageViewName = EDischargeSummary.CreateImageViewName(null, null, null, index + " X-Ray - " + examinationRequestName, null);
              index++;
            }

            imagingExaminationRequest.ImageDetails = imageDetails;
          }

          imagingExaminationRequest.StudyIdentifier = imagingExaminationRequest.StudyIdentifier = BaseCDAModel.CreateInstanceIdentifier(BaseCDAModel.CreateGuid(), "Accession Number Group: 0008  Element: 0050");

          return imagingExaminationRequest;
        }

        #endregion

    }
}
