/*
 * 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 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.DischargeSummary;


namespace Nehta.VendorLibrary.CDA.Sample
{
    /// <summary>
    /// Demonstrates the reuse of header objects in the CDA Libary 
    /// </summary>
    public class GenericObjectReuseSample
    {
        /// <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"), 
                     BaseCDAModel.CreateIdentifier
                     (
                         "SampleAuthority", 
                         HealthcareIdentifierGeographicArea.StateOrTerritoryIdentifier, 
                         "457456", 
                         "1.22.333.444.55555", 
                     BaseCDAModel.CreateCodableText("1.1.1.1.1.1", CodingSystem.NCTIS, "DisplayName", "Original Text", null)
                     )
                };

            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.CreateIdentifier("SampleAuthority", null, null, "1.2.3.4.5.66666", null), 
                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);
                                    
            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();

            if (!mandatoryOnly)
            {
                // custodian/assignedCustodian/representedCustodianOrganization/<Entity Identifier>
                custodian.Organisation.Identifiers = new List<Identifier> { 
                    BaseCDAModel.CreateIdentifier("SampleAuthority", null, null, "1.2.3.4.77777", null),
                    BaseCDAModel.CreateHealthIdentifier(HealthIdentifierType.HPII, "8003620833333789") 
                };

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

                // 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);

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

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

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

                // 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/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 };

                var name2 = BaseCDAModel.CreatePersonName();
                name2.GivenNames = new List<string> { "Davey" };
                name2.FamilyName = "Wong";
                name2.Titles = new List<string> { "Brother" };
                name2.NameUsages = new List<NameUsage> { NameUsage.NewbornName };

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

                // 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") 
                };
            }
            
        }
    }
}
