/// <summary>Generates a bed with random properties.</summary>
        /// <param name="availabilityStatus">The availability status.</param>
        /// <param name="operationalStatus"> The operational status.</param>
        /// <param name="bedTypes">          List of types of the bed.</param>
        /// <param name="org">          The managing organization.</param>
        /// <param name="parentLocation">    The parent location.</param>
        /// <returns>The bed.</returns>
        public static Location GenerateBed(
            string availabilityStatus,
            string operationalStatus,
            List <string> bedTypes,
            Organization org,
            Location parentLocation)
        {
            Location loc = new Location()
            {
                Id                = NextId,
                Status            = GetLocationStatus(availabilityStatus),
                OperationalStatus = FhirTriplet.OperationalStatus(operationalStatus).GetCoding(),
                Type              = (bedTypes == null) ? null : ConceptsForBedTypes(bedTypes),
                Mode              = Location.LocationMode.Instance,
                PhysicalType      = FhirTriplet.PhysicalTypeBed.GetConcept(),
            };

            if (org != null)
            {
                loc.ManagingOrganization = new ResourceReference($"{org.ResourceType}/{org.Id}");
            }

            if (parentLocation != null)
            {
                loc.PartOf = new ResourceReference($"{loc.ResourceType}/{parentLocation.Id}");
            }

            return(loc);
        }
        /// <summary>Updates the bed configuration.</summary>
        /// <param name="bed"> [in,out] The bed.</param>
        /// <param name="next">The next.</param>
        public static void UpdateBedConfiguration(
            ref Location bed,
            BedConfiguration next)
        {
            if (bed == null)
            {
                throw new ArgumentNullException(nameof(bed));
            }

            if (next == null)
            {
                throw new ArgumentNullException(nameof(next));
            }

            bed.Status            = GetLocationStatus(next.Availability);
            bed.OperationalStatus = FhirTriplet.OperationalStatus(next.Status).GetCoding();
        }
        /// <summary>Generates a measure report.</summary>
        /// <param name="org">           The organization.</param>
        /// <param name="parentLocation">The parent location.</param>
        /// <param name="period">        The period.</param>
        /// <param name="bedsByConfig">  The beds by configuration.</param>
        /// <returns>The measure report.</returns>
        public static MeasureReport GenerateBedMeasureReportV01(
            Organization org,
            Location parentLocation,
            Period period,
            Dictionary <BedConfiguration, List <Location> > bedsByConfig)
        {
            if (org == null)
            {
                throw new ArgumentNullException(nameof(org));
            }

            if (parentLocation == null)
            {
                throw new ArgumentNullException(nameof(parentLocation));
            }

            if (period == null)
            {
                throw new ArgumentNullException(nameof(period));
            }

            if (bedsByConfig == null)
            {
                throw new ArgumentNullException(nameof(bedsByConfig));
            }

            int totalBedCount = 0;
            List <MeasureReport.StratifierGroupComponent> stratums = new List <MeasureReport.StratifierGroupComponent>();

            foreach (BedConfiguration bedConfig in bedsByConfig.Keys)
            {
                if (bedsByConfig[bedConfig].Count == 0)
                {
                    continue;
                }

                totalBedCount += bedsByConfig[bedConfig].Count;

                stratums.Add(new MeasureReport.StratifierGroupComponent()
                {
                    MeasureScore = new Quantity(bedsByConfig[bedConfig].Count, "Number"),
                    Component    = new List <MeasureReport.ComponentComponent>()
                    {
                        new MeasureReport.ComponentComponent()
                        {
                            Code  = FhirTriplet.SanerAvailabilityStatus.GetConcept(),
                            Value = FhirTriplet.AvailabilityStatus(bedConfig.Availability).GetConcept(),
                        },
                        new MeasureReport.ComponentComponent()
                        {
                            Code  = FhirTriplet.SanerOperationalStatus.GetConcept(),
                            Value = FhirTriplet.OperationalStatus(bedConfig.Status).GetConcept(),
                        },
                        new MeasureReport.ComponentComponent()
                        {
                            Code  = FhirTriplet.SanerType.GetConcept(),
                            Value = FhirTriplet.BedType(bedConfig.Type).GetConcept(),
                        },
                        new MeasureReport.ComponentComponent()
                        {
                            Code  = FhirTriplet.SanerFeature.GetConcept(),
                            Value = FhirTriplet.BedFeature(bedConfig.Feature).GetConcept(),
                        },
                        new MeasureReport.ComponentComponent()
                        {
                            Code  = FhirTriplet.SanerLocation.GetConcept(),
                            Value = new CodeableConcept(
                                $"{SystemLiterals.SanerCharacteristic}/partOf",
                                $"{parentLocation.ResourceType}/{parentLocation.Id}"),
                        },
                    },
                });
            }

            MeasureReport.GroupComponent component = new MeasureReport.GroupComponent()
            {
                MeasureScore = new Quantity(totalBedCount, "Number"),
                Stratifier   = new List <MeasureReport.StratifierComponent>()
                {
                    new MeasureReport.StratifierComponent()
                    {
                        Stratum = stratums,
                    },
                },
            };

            return(new MeasureReport()
            {
                Id = NextId,
                Status = MeasureReport.MeasureReportStatus.Complete,
                Type = MeasureReport.MeasureReportType.Summary,
                Date = new FhirDateTime(new DateTimeOffset(DateTime.Now)).ToString(),
                Period = period,
                Measure = SystemLiterals.MeasureReportMeasurement,
                Reporter = new ResourceReference($"{org.ResourceType}/{org.Id}"),
                Group = new List <MeasureReport.GroupComponent>()
                {
                    component
                },
                Text = new Narrative()
                {
                    Div = $"<div xmlns=\"http://www.w3.org/1999/xhtml\">" +
                          $" {org.Name} Bed report for" +
                          $" {period.Start.ToString(CultureInfo.InvariantCulture)}" +
                          $" to" +
                          $" {period.End.ToString(CultureInfo.InvariantCulture)}</div>",
                },
            });
        }
        /// <summary>Generates a group.</summary>
        /// <exception cref="ArgumentNullException">Thrown when one or more required arguments are null.</exception>
        /// <param name="org">           The managing organization.</param>
        /// <param name="parentLocation">The parent location.</param>
        /// <param name="name">          The name.</param>
        /// <param name="bedConfig">     The bed configuration this group represents.</param>
        /// <param name="bedCount">      Number of beds.</param>
        /// <param name="period">        The period.</param>
        /// <returns>The group.</returns>
        public static Group GenerateGroup(
            Organization org,
            Location parentLocation,
            string name,
            BedConfiguration bedConfig,
            int bedCount,
            Period period)
        {
            if (org == null)
            {
                throw new ArgumentNullException(nameof(org));
            }

            if (parentLocation == null)
            {
                throw new ArgumentNullException(nameof(parentLocation));
            }

            if (bedConfig == null)
            {
                throw new ArgumentNullException(nameof(bedConfig));
            }

            List <Group.CharacteristicComponent> characteristics = new List <Group.CharacteristicComponent>()
            {
                new Group.CharacteristicComponent()
                {
                    Code    = FhirTriplet.SanerAvailabilityStatus.GetConcept(),
                    Value   = FhirTriplet.AvailabilityStatus(bedConfig.Availability).GetConcept(),
                    Exclude = false,
                },
                new Group.CharacteristicComponent()
                {
                    Code    = FhirTriplet.SanerOperationalStatus.GetConcept(),
                    Value   = FhirTriplet.OperationalStatus(bedConfig.Status).GetConcept(),
                    Exclude = false,
                },
                new Group.CharacteristicComponent()
                {
                    Code    = FhirTriplet.SanerType.GetConcept(),
                    Value   = FhirTriplet.BedType(bedConfig.Type).GetConcept(),
                    Exclude = false,
                },
                new Group.CharacteristicComponent()
                {
                    Code    = FhirTriplet.SanerFeature.GetConcept(),
                    Value   = FhirTriplet.BedFeature(bedConfig.Feature).GetConcept(),
                    Exclude = false,
                },
                new Group.CharacteristicComponent()
                {
                    Code    = FhirTriplet.SanerLocation.GetConcept(),
                    Value   = new ResourceReference($"{parentLocation.ResourceType}/{parentLocation.Id}"),
                    Exclude = false,
                },
                new Group.CharacteristicComponent()
                {
                    // Code = FhirTriplet.SanerPeriod.GetConcept(),
                    Code    = FhirTriplet.MeasureReportPeriod.GetConcept(),
                    Value   = FhirTriplet.EmptyRequired.GetConcept(),
                    Period  = period,
                    Exclude = false,
                },
            };

            return(new Group()
            {
                Id = NextId,
                Type = Group.GroupType.Device,
                Actual = true,
                Code = FhirTriplet.PhysicalTypeBed.GetConcept(),
                Name = name,
                Quantity = bedCount,
                ManagingEntity = new ResourceReference($"{org.ResourceType}/{org.Id}"),
                Characteristic = characteristics,
                Text = new Narrative()
                {
                    Div = $"<div xmlns=\"http://www.w3.org/1999/xhtml\">" +
                          $" {org.Name} Beds of type: {bedConfig.Type} ({bedConfig.Feature})" +
                          $" Flagged {bedConfig.Availability} and {bedConfig.Status}</div>",
                },
            });
        }