using System.Text.Json;
using System.Text.Json.Serialization;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
namespace PlayerNotes;
///
/// Loads, saves, and validates the PlayerNotes.json data file. The file lives in this
/// plugin's config directory (e.g. %APPDATA%\XIVLauncher\plugin_config\PlayerNotes\)
/// and is also the export/import format for moving lists between PCs.
///
public class Storage
{
private static readonly JsonSerializerOptions SerializerOptions = new()
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
// Users edit this file by hand to manage tags; allow (and ignore) comments.
ReadCommentHandling = JsonCommentHandling.Skip,
};
private readonly IPluginLog log;
public PlayerNotesData Data { get; private set; } = new();
public string FilePath { get; }
public Storage(IDalamudPluginInterface pluginInterface, IPluginLog log)
{
this.log = log;
FilePath = Path.Combine(pluginInterface.ConfigFile.Directory!.FullName, "PlayerNotes.json");
Load();
}
/// Reads the data file from disk, creating it with defaults if missing.
public void Load()
{
try
{
if (File.Exists(FilePath))
{
Data = Parse(File.ReadAllText(FilePath));
log.Debug($"Loaded player notes from {FilePath}");
}
else
{
Data = new PlayerNotesData();
Save(); // create the file so users can find and edit it (tags etc.)
log.Information($"Created new data file at {FilePath}");
}
}
catch (Exception e)
{
// Never let a corrupt file kill the plugin; fall back to empty lists.
log.Error(e, "Failed to load PlayerNotes.json, starting with empty lists.");
Data = new PlayerNotesData();
}
}
/// Writes the current data to disk.
public void Save()
{
try
{
File.WriteAllText(FilePath, Serialize(Data));
}
catch (Exception e)
{
log.Error(e, "Failed to save PlayerNotes.json.");
}
}
/// Replaces the in-memory data and persists it (used by import).
public void Replace(PlayerNotesData newData)
{
Data = newData;
Save();
}
/// Parses a JSON document into validated data. Throws on invalid input.
internal static PlayerNotesData Parse(string json)
{
var data = JsonSerializer.Deserialize(json, SerializerOptions);
if (data is null)
throw new InvalidDataException("The file does not contain valid player notes data.");
data.Normalize();
return data;
}
internal static string Serialize(PlayerNotesData data) =>
JsonSerializer.Serialize(data, SerializerOptions);
}