using System.Text.Json;
using System.Text.Json.Serialization;

namespace DoomDeathmatch.Script.Score;

[Serializable]
[JsonSerializable(typeof(ScoreTable))]
public class ScoreTable
{
  private static readonly JsonSerializerOptions OPTIONS = new() { Converters = { new ScoreTableJsonConverter() } };

  public List<ScoreRow> Rows { get; } = new();

  public static ScoreTable LoadOrCreate(string parPath)
  {
    ScoreTable? table = null;

    try
    {
      using var stream = File.OpenRead(parPath);
      table = JsonSerializer.Deserialize<ScoreTable>(stream, OPTIONS);
    }
    catch (Exception)
    {
      // ignored
    }

    if (table != null)
      return table;

    table = new ScoreTable();
    ScoreTable.Save(table, parPath);

    return table;
  }

  public static void Save(ScoreTable parTable, string parPath)
  {
    using var stream = File.Create(parPath);
    JsonSerializer.Serialize(stream, parTable, OPTIONS);
  }
}

public class ScoreTableJsonConverter : JsonConverter<ScoreTable>
{
  public override ScoreTable? Read(
    ref Utf8JsonReader parReader,
    Type parTypeToConvert,
    JsonSerializerOptions? parOptions
  )
  {
    var rows = JsonSerializer.Deserialize<ScoreRow[]>(ref parReader, parOptions);
    if (rows == null)
      return null;

    var scoreTable = new ScoreTable();
    foreach (var row in rows)
    {
      scoreTable.Rows.Add(row);
    }

    scoreTable.Rows.Sort((parX, parY) => parY.Score.CompareTo(parX.Score));

    return scoreTable;
  }

  public override void Write(Utf8JsonWriter parWriter, ScoreTable parValue, JsonSerializerOptions parOptions)
  {
    JsonSerializer.Serialize(parWriter, parValue.Rows, parOptions);
  }
}