poe2-bot/src/Roboto.Core/ProfileManager.cs
2026-03-03 12:54:30 -05:00

174 lines
4.7 KiB
C#

using System.Text.Json;
using System.Text.Json.Serialization;
namespace Roboto.Core;
public sealed class ProfileManager
{
private static readonly JsonSerializerOptions JsonOpts = new()
{
WriteIndented = true,
Converters = { new JsonStringEnumConverter() },
};
private readonly string _profilesDir;
private readonly string _assignmentsFile;
private readonly object _lock = new();
private Dictionary<string, string> _assignments = new(); // charName → profileName
public ProfileManager(string profilesDir = "profiles")
{
_profilesDir = Path.GetFullPath(profilesDir);
_assignmentsFile = Path.Combine(_profilesDir, "_assignments.json");
EnsureDirectory();
LoadAssignments();
}
public CharacterProfile LoadForCharacter(string charName)
{
lock (_lock)
{
if (_assignments.TryGetValue(charName, out var profileName))
{
var profile = LoadProfile(profileName);
if (profile is not null)
return profile;
}
// Create default profile for this character
var defaultName = $"{charName}_Default";
var defaultProfile = new CharacterProfile { Name = defaultName };
SaveProfile(defaultProfile);
_assignments[charName] = defaultName;
SaveAssignments();
return defaultProfile;
}
}
public void Save(CharacterProfile profile)
{
lock (_lock)
{
profile.LastModified = DateTime.UtcNow;
SaveProfile(profile);
}
}
public CharacterProfile? Duplicate(string profileName, string newName)
{
lock (_lock)
{
var source = LoadProfile(profileName);
if (source is null) return null;
source.Name = newName;
source.CreatedAt = DateTime.UtcNow;
source.LastModified = DateTime.UtcNow;
SaveProfile(source);
return source;
}
}
public void AssignToCharacter(string charName, string profileName)
{
lock (_lock)
{
_assignments[charName] = profileName;
SaveAssignments();
}
}
public void Delete(string profileName)
{
lock (_lock)
{
var path = ProfilePath(profileName);
if (File.Exists(path))
File.Delete(path);
// Remove any assignments pointing to this profile
var toRemove = _assignments
.Where(kv => kv.Value == profileName)
.Select(kv => kv.Key)
.ToList();
foreach (var key in toRemove)
_assignments.Remove(key);
if (toRemove.Count > 0)
SaveAssignments();
}
}
public List<string> ListProfiles()
{
lock (_lock)
{
EnsureDirectory();
return Directory.GetFiles(_profilesDir, "*.json")
.Select(Path.GetFileNameWithoutExtension)
.Where(n => n is not null && !n.StartsWith("_"))
.Cast<string>()
.OrderBy(n => n)
.ToList();
}
}
public string? GetAssignment(string charName)
{
lock (_lock)
{
return _assignments.GetValueOrDefault(charName);
}
}
private CharacterProfile? LoadProfile(string name)
{
var path = ProfilePath(name);
if (!File.Exists(path)) return null;
try
{
var json = File.ReadAllText(path);
return JsonSerializer.Deserialize<CharacterProfile>(json, JsonOpts);
}
catch
{
return null;
}
}
private void SaveProfile(CharacterProfile profile)
{
EnsureDirectory();
var json = JsonSerializer.Serialize(profile, JsonOpts);
File.WriteAllText(ProfilePath(profile.Name), json);
}
private void LoadAssignments()
{
if (!File.Exists(_assignmentsFile)) return;
try
{
var json = File.ReadAllText(_assignmentsFile);
_assignments = JsonSerializer.Deserialize<Dictionary<string, string>>(json, JsonOpts) ?? new();
}
catch
{
_assignments = new();
}
}
private void SaveAssignments()
{
EnsureDirectory();
var json = JsonSerializer.Serialize(_assignments, JsonOpts);
File.WriteAllText(_assignmentsFile, json);
}
private void EnsureDirectory()
{
if (!Directory.Exists(_profilesDir))
Directory.CreateDirectory(_profilesDir);
}
private string ProfilePath(string name) => Path.Combine(_profilesDir, $"{name}.json");
}