Agenda/Career.cs
using System.Text.Json.Nodes;
using Sandbox.Services;

namespace PlanetMeat;

public sealed class Career( Scene scene ) : GameObjectSystem<Career>( scene )
{
	const string ENTRY_TYPE_SAVE = "save";
	const string PROGRESS_FILE_NAME = "progress.json";
	const string STATS_FILE_NAME = "stats.json";

	private IEnumerable<KeyValuePair<string, ISaveTarget>> ProgressSaveTargets => field ??= [
		new("Meat", Bank.Current.GetAccount( "meat" )),
		new("Research", Research.Current),
	];

	public bool IsFreshSave { get; private set; } = true;
	public int HighestRoundCompleted
	{
		get;
		set
		{
			if ( value == 0 || value > field )
			{
				field = value;
				if ( value > 0 )
					Stats.SetValue( "peak_round", value );
			}
		}
	} = 0;

	public StatContext RoundStats { get; } = new();
	public StatContext RunStats { get; } = new();
	public StatContext CareerStats { get; } = new();

	private Storage.Entry _saveEntry = null;
	private Storage.Entry SaveEntry
	{
		get
		{
			if ( NeedsLoad )
				LoadSave();
			return _saveEntry;
		}
		set => LoadSave( value );
	}
	public bool NeedsLoad => _saveEntry is null;

	private static Storage.Entry FetchSave()
	{
		var extantSaves = Storage.GetAll( ENTRY_TYPE_SAVE );
		if ( extantSaves.Length > 0 )
			return extantSaves[0];
		return Storage.CreateEntry( ENTRY_TYPE_SAVE );
	}

	public void LoadSave( Storage.Entry s = null )
	{
		s ??= FetchSave();
		IsFreshSave = !s.Files.FileExists( PROGRESS_FILE_NAME );
		if ( _saveEntry != s )
		{
			_saveEntry = s;
			if ( s.Files.ReadJson<JsonObject>( PROGRESS_FILE_NAME ) is JsonObject progress )
				ProgressSaveTargets.LoadFromSaveObject( progress );
			if ( s.Files.ReadJson<JsonObject>( STATS_FILE_NAME ) is JsonObject stats )
				CareerStats.LoadFromSave( stats );

			HighestRoundCompleted = 0;
			HighestRoundCompleted = s.GetMeta( nameof( HighestRoundCompleted ), 0 );
		}
	}

	public void SaveProgress()
	{
		SaveEntry.Files.WriteJson( PROGRESS_FILE_NAME, ProgressSaveTargets.ToSaveObject() );
		SaveEntry.SetMeta( nameof( HighestRoundCompleted ), HighestRoundCompleted );
		IsFreshSave = false;
	}

	public void Reset()
	{
		HqNavigator.View = HqNavigator.Views.None;

		RoundStats.Reset();
		RunStats.Reset();
		CareerStats.Reset();

		ProgressSaveTargets.ClearSavedInfo();

		SaveEntry.Delete();
		SaveEntry = null;
	}

	public void SetStat( string ident, double value )
	{
		Stats.SetValue( ident, value );
		RoundStats.SetStat( ident, value );
	}

	public void IncrementStat( string ident, double amount = 1.0 )
	{
		Stats.Increment( ident, amount );
		RoundStats.IncrementStat( ident, amount );
	}

	public void CommitRoundStats()
	{
		RoundStats.MergeInto( RunStats );
	}

	public void CommitRunStats()
	{
		CommitRoundStats();
		RunStats.MergeInto( CareerStats );
		SaveEntry.Files.WriteJson( STATS_FILE_NAME, CareerStats.NextSave );
	}

	public static double GetGlobalStat( string ident )
	{
		return Stats.Global.Get( ident ).Sum;
	}
}