using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace MultiversalDiplomacy.Model;
///
/// Represents a multiversal coordinate at which a state of the map exists.
///
[JsonConverter(typeof(SeasonJsonConverter))]
public struct Season(string timeline, int turn)
{
///
/// The root season of every game. This is defined to avoid any confusion about what the first turn or timeline
/// should be or what season to use to key into a fresh .
///
public static readonly Season First = new(Timelines.IntToString(0), 0);
///
/// The timeline to which this season belongs.
///
public string Timeline { get; } = timeline;
///
/// The current turn, beginning at 0. Each season (spring and fall) is one turn.
/// Phases that only occur after the fall phase occur when Turn % 2 == 1.
/// The current year is (Turn / 2) + 1901.
///
public int Turn { get; } = turn;
///
/// The multiversal designation of this season.
///
[JsonIgnore]
public readonly string Key => $"{this.Timeline}{this.Turn}";
///
/// Create a new season from a tuple coordinate.
///
public Season((string timeline, int turn) coord) : this(coord.timeline, coord.turn) { }
///
/// Create a new season from a combined string designation.
///
///
public Season(string designation) : this(SplitKey(designation)) { }
///
/// Extract the timeline and turn components of a season designation.
///
/// A timeline-turn season designation.
/// The timeline and turn components.
///
public static (string timeline, int turn) SplitKey(string seasonKey)
{
int i = 1;
for (; !char.IsAsciiDigit(seasonKey[i]) && i < seasonKey.Length; i++);
return int.TryParse(seasonKey.AsSpan(i), out int turn)
? (seasonKey[..i], turn)
: throw new FormatException($"Could not parse turn from {seasonKey}");
}
public override readonly string ToString() => Key;
///
/// Seasons are essentially 2D points, so they are equal when their components are equal.
///
public override readonly bool Equals([NotNullWhen(true)] object? obj)
=> obj is Season season
&& Timeline == season.Timeline
&& Turn == season.Turn;
public static bool operator ==(Season one, Season two) => one.Equals(two);
public static bool operator !=(Season one, Season two) => !(one == two);
public override readonly int GetHashCode() => (Timeline, Turn).GetHashCode();
}