/// <summary>
 /// Set billingPeriodStart and -End. accountingPeriod.Begin and accountingPeriod.End can not be null
 /// due to the validation process. There must be a billing period.
 /// </summary>
 /// <param name="accountingPeriod"></param>
 public void SetTotalBillingPeriod(Taf2Data accountingPeriod)
 {
     this.billingPeriodStart = accountingPeriod.Begin;
     this.billingPeriodEnd   = accountingPeriod.End;
 }
        /// <inheritdoc />
        /// <summary>
        /// Calculates the derived registers for Taf2.
        /// </summary>
        /// <param name="device">Data from the SMGW. There should be just original value lists.</param>
        /// <param name="supplier">The calculation data from the supplier.</param>
        /// <returns>An ITaf2Data instance. The object contains the calculated data.</returns>
        public TafAdapterData Calculate(UsagePointAdapterTRuDI device, UsagePointLieferant supplier)
        {
            this.originalValueLists =
                device.MeterReadings.Where(mr => mr.IsOriginalValueList()).Select(mr => new OriginalValueList(mr, device.ServiceCategory.Kind ?? Kind.Electricity)).ToList();

            if (!this.originalValueLists.Any())
            {
                throw new InvalidOperationException("Es ist keine originäre Messwertliste verfügbar.");
            }

            var registers = supplier.GetRegister();

            this.UpdateReadingTypeFromOriginalValueList(registers);

            var accountingPeriod = new Taf2Data(registers, supplier.AnalysisProfile.TariffStages);
            var dayProfiles      = supplier.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles;

            foreach (var ovl in this.originalValueLists)
            {
                var bpStart = ovl.MeterReading.GetFirstReadingTimestamp(supplier.AnalysisProfile.BillingPeriod.Start, supplier.AnalysisProfile.BillingPeriod.GetEnd());
                var bpEnd   = ovl.MeterReading.GetLastReadingTimestamp(supplier.AnalysisProfile.BillingPeriod.Start, supplier.AnalysisProfile.BillingPeriod.GetEnd());
                if (bpEnd == null || bpStart == null || bpStart == bpEnd)
                {
                    throw new InvalidOperationException("Keine Messwerte innerhalb des Abbrechnungszeitraums gefunden.");
                }

                accountingPeriod.SetDates(bpStart.Value, bpEnd.Value);
                this.SetTotalBillingPeriod(accountingPeriod);

                var    validDayProfiles   = dayProfiles.GetValidDayProfilesForMeterReading(ovl.Obis, supplier.AnalysisProfile.TariffStages);
                var    specialDayProfiles = this.GetSpecialDayProfiles(supplier, validDayProfiles, accountingPeriod.Begin, accountingPeriod.End);
                long   latestReading      = 0;
                ushort latestTariffId     = 63;

                // Check if the lists validDayProfiles and special DayProfiles are null or empty
                if (!this.CheckUsedLists(validDayProfiles, specialDayProfiles))
                {
                    continue;
                }

                // Calculation of the single days (latestReading and latestTariffId are needed for days across gap detection)
                foreach (SpecialDayProfile profile in specialDayProfiles)
                {
                    var currentDayData = this.GetDayData(profile, dayProfiles, ovl.MeterReading, supplier, latestReading, latestTariffId);
                    if (!(currentDayData.day.Start == DateTime.MinValue) || currentDayData.day.MeasuringRanges.Count != 0)
                    {
                        accountingPeriod.Add(currentDayData.day);
                    }
                    latestReading  = currentDayData.latestReading;
                    latestTariffId = currentDayData.tariffId;
                }

                // Set the initial overall meter reading
                accountingPeriod.AddInitialReading(new Reading()
                {
                    Amount   = accountingPeriod.AccountingSections.First().Reading.Amount,
                    ObisCode = ovl.Obis
                });
            }

            accountingPeriod.OrderSections();
            return(new TafAdapterData(typeof(Taf2SummaryView), typeof(Taf2DetailView), accountingPeriod));
        }