Desk.cs
namespace PixelPusher;

public sealed class ProjectSave
{
	public int Version { get; set; } = 1;
	public string Name { get; set; }
	public PixelSave Sprite { get; set; }
	public TilesetSave Tileset { get; set; }
	public StageSave Stage { get; set; }
	public ChipSave Chip { get; set; }
}

public static class Desk
{
	public const string DraftFile = "desk_draft.json";

	public static bool Ready { get; private set; }
	public static string Name = "My Desk";
	public static PixelDoc Sprite;
	public static TilesetDoc Tileset;
	public static StageDoc Stage;
	public static ChipDoc Chip;
	public static bool Dirty;
	public static float AutosaveIn = 30f;

	public static void Boot()
	{
		if ( Ready )
			return;

		if ( TryLoadDraft() )
		{
			Ready = true;
			Coach.Line = "Draft restored. Push a pixel.";
			return;
		}

		Sprite = StarterPack.Coin();
		Tileset = StarterPack.CornerStore();
		Stage = StarterPack.TutorialStage();
		Chip = new ChipDoc();
		Name = "Stock the Cooler";
		Ready = true;
		Dirty = false;
		Coach.Line = "Push pixels. This is PIXEL STUDIO.";
	}

	public static void Touch()
	{
		Dirty = true;
	}

	public static void Tick()
	{
		if ( !Ready )
			return;
		if ( !Dirty )
			return;

		AutosaveIn -= Time.Delta;
		if ( AutosaveIn <= 0f )
			Autosave( quiet: true );
	}

	public static void Autosave( bool quiet )
	{
		if ( !Ready )
			return;
		try
		{
			FileSystem.Data.WriteJson( DraftFile, ToSave() );
			Dirty = false;
			AutosaveIn = 30f;
			if ( !quiet )
				GameFlow.ShowToast( "desk saved" );
		}
		catch ( Exception e )
		{
			Log.Warning( $"[PIXEL PUSHER] autosave failed: {e.Message}" );
		}
	}

	public static ProjectSave ToSave()
	{
		return new ProjectSave
		{
			Version = 1,
			Name = Name,
			Sprite = Sprite?.ToSave(),
			Tileset = Tileset?.ToSave(),
			Stage = Stage?.ToSave(),
			Chip = Chip?.ToSave()
		};
	}

	public static void Apply( ProjectSave save )
	{
		if ( save is null )
			return;
		Name = string.IsNullOrWhiteSpace( save.Name ) ? "My Desk" : save.Name;
		Sprite = PixelDoc.FromSave( save.Sprite );
		Tileset = TilesetDoc.FromSave( save.Tileset );
		Stage = StageDoc.FromSave( save.Stage );
		Chip = ChipDoc.FromSave( save.Chip );
		Ready = true;
		Dirty = false;
		AutosaveIn = 30f;
	}

	static bool TryLoadDraft()
	{
		try
		{
			if ( !FileSystem.Data.FileExists( DraftFile ) )
				return false;
			var save = FileSystem.Data.ReadJsonOrDefault<ProjectSave>( DraftFile, null );
			if ( save is null )
				return false;
			Apply( save );
			return true;
		}
		catch
		{
			return false;
		}
	}
}