using System;
using MfGames.Gallium;
using MfGames.Nitride.Generators;
using NodaTime;
namespace MfGames.Nitride.Temporal.Schedules;
///
/// A schedule that uses the `UPath` of the entity to determine an offset from
/// a starting point and calculates the information from there.
///
[WithProperties]
public partial class PeriodicPathRegexSchedule : PathRegexScheduleBase
{
public PeriodicPathRegexSchedule()
{
this.CaptureOffset = -1;
}
///
/// Gets or sets the period between each matching entity. The period is
/// amount of time between each item based on the number. So the first will
/// be on the ScheduleDate, the second SchedulePeriod later, the third
/// SchedulePeriod after the second, etc. More precisely, the date for
/// any item TimeSpan * ((int)CaptureGroup + (int)CaptureOffset).
///
public string? SchedulePeriod { get; set; }
///
/// Gets or sets the schedule period as a TimeSpan object. This is converted
/// from SchedulePeriod using https://github.com/pengowray/TimeSpanParser.
/// If the value is null or blank or "immediate", then this will be instant
/// (TimeSpan.Zero).
///
public virtual TimeSpan? SchedulePeriodTimeSpan
{
get => TimeSpanHelper.Parse(this.SchedulePeriod);
set => this.SchedulePeriod = value?.ToString();
}
///
/// Gets or sets when the first item is scheduled.
///
public DateTime? ScheduleStart { get; set; }
///
protected override Entity Apply(
Entity entity,
int number,
TimeService timeService)
{
// If we have a "never", then we skip it.
TimeSpan? period = this.SchedulePeriodTimeSpan;
DateTime? start = this.ScheduleStart;
if (period == null || start == null)
{
return entity;
}
// Figure out the time from the start.
DateTime when = start.Value + period.Value * number;
Instant instant = timeService.CreateInstant(when);
// If the time hasn't past, then we don't apply it.
Instant now = timeService.Clock.GetCurrentInstant();
return instant > now
? entity
: this.Apply(entity, number, instant);
}
///
/// Applies the schedule to the entity based on the number and instant
/// given.
///
protected virtual Entity Apply(
Entity entity,
int number,
Instant instant)
{
return entity.Set(instant);
}
}