Park/Goals/Scenario.cs
using HC3.Persistence;
using System.Collections.Immutable;

namespace HC3;

/// <summary>
/// Defines the information for a scenario -- a scenario holds multiple goal groups. See <see cref="GoalGroup"/>
/// </summary>
public partial class Scenario : Component, ISaveDataProperty<ImmutableArray<GoalGroup.SaveData>>
{
	[Property] public string Title { get; set; }
	[Property] public string Description { get; set; }

	string ISaveDataProperty.PropertyName => $"Scenario";
	int ISaveDataProperty.PropertyOrder => 99_000;

	ImmutableArray<GoalGroup.SaveData> ISaveDataProperty<ImmutableArray<GoalGroup.SaveData>>.WriteValue( Scene scene )
	{
		var data = new List<GoalGroup.SaveData>();

		foreach ( var manager in scene.GetAll<GoalGroup>() )
		{
			var managerSave = new GoalGroup.SaveData( manager.Title, manager.GetGoals()
				.Select( x => x.GetSerialized() )
				.ToImmutableArray() );

			data.Add( managerSave );
		}

		return data.ToImmutableArray();
	}

	void ISaveDataProperty<ImmutableArray<GoalGroup.SaveData>>.ReadValue( Scene scene, ImmutableArray<GoalGroup.SaveData> data )
	{
		foreach ( var groupData in data )
		{
			var group = scene.GetAll<GoalGroup>()
				.FirstOrDefault( x => x.Title.Equals( groupData.Name, System.StringComparison.InvariantCultureIgnoreCase ) );

			var goals = group.GetGoals();
			foreach ( var goalData in groupData.Goals )
			{
				var goal = goals.FirstOrDefault( x => x.GoalName.Equals( goalData.GoalName, System.StringComparison.InvariantCultureIgnoreCase ) );
				if ( goal.IsValid() )
				{
					goal.Deserialize( goalData );
				}
			}
		}
	}
}