protected void AnalyzeSpaceStatusModelForOverstayViolation(SpaceStatusModel model)
        {
            // There is nothing to do if this event is not for occupied status
            if ((model.BayOccupancyState == OccupancyState.Empty) || (model.BayOccupancyState == OccupancyState.NotAvailable) ||
                (model.BayOccupancyState == OccupancyState.OutOfDate) || (model.BayOccupancyState == OccupancyState.Unknown))
            {
                return;
            }

            // Find the space asset associated with this data model.  If the space is "inactive" (based on the "IsActive" column of "HousingMaster" table in database),
            // then we will not consider the space to be in a violating state, because the sensor is effectively marked as bad/untrusted
            SpaceAsset spcAsset = GetSpaceAsset(model.MeterID, model.BayID);

            if (spcAsset != null)
            {
                // Nothing more to do if the space isn't active
                if (spcAsset.IsActive == false)
                {
                    return;
                }
            }

            // Resolve the associated area for the meter
            int areaID = ResolveAreaIDForMeterID(model.MeterID);

            // Try to obtain the regulated hours applicable to this meter
            RegulatedHoursGroup regulatedHours = RegulatedHoursGroupRepository.Repository.GetBestGroupForMeter(this._CustomerConfig.CustomerId, areaID, model.MeterID);

            // If no regulated hour defintions came back, then we are unable to calculate any overstay violation, so just exit
            if ((regulatedHours == null) || (regulatedHours.Details == null) || (regulatedHours.Details.Count == 0))
            {
                return;
            }

            DateTime NowAtDestination = Convert.ToDateTime(this._CustomerConfig.DestinationTimeZoneDisplayName);
            DateTime ruleStart        = DateTime.MinValue;
            DateTime ruleEnd          = DateTime.MinValue;

            TimeSlot OccupiedSegment = new TimeSlot(model.BayVehicleSensingTimestamp, NowAtDestination);

            // We need to check if this single occupancy event is an overstay violation for multiple rules, or even for more than one day, etc.
            while (OccupiedSegment.Start < NowAtDestination)
            {
                // Determine the day of week that is involved
                int dayOfWeek = (int)OccupiedSegment.Start.DayOfWeek;

                // Loop through the daily rules and see which ones overlap with our occupied period
                foreach (RegulatedHoursDetail detail in regulatedHours.Details)
                {
                    // Skip this one if its for a different day of the week
                    if (detail.DayOfWeek != dayOfWeek)
                    {
                        continue;
                    }

                    // Determine if the occupied timeslot overlaps with the rule's timeslot
                    ruleStart = new DateTime(OccupiedSegment.Start.Year, OccupiedSegment.Start.Month, OccupiedSegment.Start.Day, detail.StartTime.Hour, detail.StartTime.Minute, 0);
                    ruleEnd   = new DateTime(OccupiedSegment.Start.Year, OccupiedSegment.Start.Month, OccupiedSegment.Start.Day, detail.EndTime.Hour, detail.EndTime.Minute, 59);
                    TimeSlot RuleSegment = new TimeSlot(ruleStart, ruleEnd);

                    // We only care about this overlapping rule if the MaxStayMinutes is greater than zero (zero or less means there is no MaxStay that is enforced),
                    // or if it's explicitly set as a "No Parking" regulation
                    if ((RuleSegment.OverlapsWith(OccupiedSegment) == true) &&
                        ((detail.MaxStayMinutes > 0) || (string.Compare(detail.Type, "No Parking", true) == 0))
                        )
                    {
                        // Normally we will use the verbatim value of the max stay minutes, but if its a "No Parking", we will always take that to mean 0 minutes is the actual max
                        int timeLimitMinutes = detail.MaxStayMinutes;
                        if (string.Compare(detail.Type, "No Parking", true) == 0)
                        {
                            timeLimitMinutes = 0;
                        }

                        // Get the intersection of the overlaps so we know how long the vehicle has been occupied during this rule
                        TimeSlot OccupiedIntersection = RuleSegment.GetIntersection(OccupiedSegment);

                        // Determine if the vehicle has been occupied during this rule segment in excess of the MaxStayMinutes
                        if (OccupiedIntersection != null)
                        {
                            if (OccupiedIntersection.Duration.TotalMinutes >= timeLimitMinutes)
                            {
                                // We will check to see if this violated regulated period matches the current regulated period.
                                // But since it could be occupied for a long time, we must also check the current date, in addition to day of week and time of day!
                                bool     currDetailMatchesCurrentRegulatedPeriod = false;
                                DateTime TodayAtDestination = Convert.ToDateTime(this._CustomerConfig.DestinationTimeZoneDisplayName); //UtilityClasses.TimeZoneInfo.ConvertTimeZoneToTimeZone(DateTime.Now, this._CustomerConfig.ServerTimeZone, this._CustomerConfig.CustomerTimeZone).Date;
                                if (OccupiedSegment.Start >= TodayAtDestination)
                                {
                                    if (model.ActiveRegulationPeriod != null)
                                    {
                                        RegulatedHoursDetailLogicalComparer comparer = new RegulatedHoursDetailLogicalComparer();
                                        currDetailMatchesCurrentRegulatedPeriod = (comparer.Compare(model.ActiveRegulationPeriod, detail) == 0);
                                    }
                                }

                                // Create a new Overstay Vio Info object and add to the overall list of violations
                                OverstayViolationInfo overstay = new OverstayViolationInfo();
                                overstay.IsForCurrentRegulationPeriod = currDetailMatchesCurrentRegulatedPeriod;
                                overstay.Regulation_Date                   = new DateTime(OccupiedSegment.Start.Year, OccupiedSegment.Start.Month, OccupiedSegment.Start.Day);
                                overstay.Regulation_DayOfWeek              = detail.DayOfWeek;
                                overstay.Regulation_EndTime                = detail.EndTime;
                                overstay.Regulation_MaxStayMinutes         = detail.MaxStayMinutes; // Instead of using our calculated time limit, we will record the configured max stay minutes here, because it will be displayed
                                overstay.Regulation_StartTime              = detail.StartTime;
                                overstay.Regulation_Type                   = detail.Type;
                                overstay.DateTime_StartOfOverstayViolation = new DateTime(OccupiedIntersection.Start.Ticks).AddMinutes(timeLimitMinutes);
                                overstay.DurationOfTimeBeyondStayLimits    = new TimeSpan(OccupiedIntersection.Duration.Ticks).Add(new TimeSpan(0, (-1) * timeLimitMinutes, 0));

                                // Add this overstay info to the model's list
                                model.AllOverstayViolations.Add(overstay);

                                // If its also for the current regulation period, retain a reference to it
                                if (overstay.IsForCurrentRegulationPeriod == true)
                                {
                                    model.CurrentOverstayViolation = overstay;
                                }

                                // Mark as "Overstay Violation" status if we have a current overstay violation.  Otherwise mark
                                // as "Discretionary" because there is an overstay violation, but not for the current enforcement period
                                if (model.CurrentOverstayViolation != null)
                                {
                                    model.BayEnforcementState = EnforcementState.OverstayViolation;
                                }
                                else
                                {
                                    model.BayEnforcementState = EnforcementState.Discretionary;
                                }
                            }
                        }
                    }
                }

                // Rules for current day of week have been processed.  So now we will advance to beginning of next day and see if there are more violations that we will use
                // to add accumulated time in violation state...
                OccupiedSegment = new TimeSlot(new DateTime(OccupiedSegment.Start.Year, OccupiedSegment.Start.Month, OccupiedSegment.Start.Day).AddDays(1),
                                               NowAtDestination);
            }
        }