using System;
using System.Text.RegularExpressions;
using MfGames.Gallium;
using MfGames.Nitride.Generators;
using Zio;
namespace MfGames.Nitride.Temporal.Schedules;
///
/// A common base for a schedule that is built off the path associated with
/// the entity.
///
[WithProperties]
public abstract partial class PathRegexScheduleBase : ISchedule
{
protected PathRegexScheduleBase()
{
this.PathRegex = @"^.*?(\d+)[^\d]*$";
this.GetPath = entity => entity.Get().ToString();
this.CaptureGroup = 1;
}
///
/// Gets or sets the group number of the capture group with 1 being being the
/// first group in PathRegex.
///
public int CaptureGroup { get; set; }
///
/// Gets or sets the offset to make the resulting capture group a zero-based
/// number.
///
public int CaptureOffset { get; set; }
///
/// Gets or sets the method for retrieving the path for the entity.
///
public Func GetPath { get; set; }
///
/// Gets or sets the regular expression to identify a matching path.
///
public string? PathRegex { get; set; }
///
public virtual Entity Apply(
Entity entity,
Timekeeper timekeeper)
{
// Get the path and match it.
string path = this.GetPath(entity);
Regex? regex = this.GetRegex();
Match match = regex?.Match(path)
?? throw new NullReferenceException(
"PathRegex was not configured for the "
+ this.GetType().Name
+ ".");
if (!match.Success)
{
return entity;
}
if (match.Groups.Count < 2)
{
throw new InvalidOperationException(
"There must be at least one capture group in '"
+ this.PathRegex
+ "'.");
}
// Figure out the index/number of this entry.
string numberValue = match.Groups[this.CaptureGroup].Value;
if (!int.TryParse(numberValue, out int number))
{
throw new FormatException(
path + ": Cannot parse '" + numberValue + "' as integer.");
}
number += this.CaptureOffset;
// Pass it onto the extending class.
return this.Apply(entity, number, timekeeper);
}
///
public virtual bool CanApply(Entity entity)
{
string path = this.GetPath(entity);
Regex? regex = this.GetRegex();
Match match = regex?.Match(path)
?? throw new NullReferenceException(
"PathRegex was not configured for the "
+ this.GetType().Name
+ ".");
return match.Success;
}
///
/// Applies the schedule according to the normalized number (after
/// CaptureOffset).
///
protected abstract Entity Apply(
Entity entity,
int number,
Timekeeper timekeeper);
private Regex? GetRegex()
{
return this.PathRegex == null
? null
: new Regex(this.PathRegex);
}
}