using System.Text.Json.Serialization;

namespace Flyshot.Core.Domain;

/// <summary>
/// Describes the sampled shot-event mapping that downstream monitoring and reports consume.
/// </summary>
public sealed class ShotEvent
{
    /// <summary>
    /// Initializes a validated shot-event mapping result.
    /// </summary>
    public ShotEvent(int waypointIndex, double triggerTime, int sampleIndex, double sampleTime, IoAddressGroup addressGroup)
    {
        if (waypointIndex < 0)
        {
            throw new ArgumentOutOfRangeException(nameof(waypointIndex), "Waypoint index must be zero or positive.");
        }

        if (triggerTime < 0.0)
        {
            throw new ArgumentOutOfRangeException(nameof(triggerTime), "Trigger time must be zero or positive.");
        }

        if (sampleIndex < 0)
        {
            throw new ArgumentOutOfRangeException(nameof(sampleIndex), "Sample index must be zero or positive.");
        }

        if (sampleTime < 0.0)
        {
            throw new ArgumentOutOfRangeException(nameof(sampleTime), "Sample time must be zero or positive.");
        }

        WaypointIndex = waypointIndex;
        TriggerTime = triggerTime;
        SampleIndex = sampleIndex;
        SampleTime = sampleTime;
        AddressGroup = addressGroup ?? throw new ArgumentNullException(nameof(addressGroup));
    }

    /// <summary>
    /// Gets the original teach-waypoint index.
    /// </summary>
    [JsonPropertyName("waypointIndex")]
    public int WaypointIndex { get; }

    /// <summary>
    /// Gets the mathematically resolved trigger time.
    /// </summary>
    [JsonPropertyName("triggerTime")]
    public double TriggerTime { get; }

    /// <summary>
    /// Gets the discrete sample index selected by the trigger scheduler.
    /// </summary>
    [JsonPropertyName("sampleIndex")]
    public int SampleIndex { get; }

    /// <summary>
    /// Gets the sampled trigger time used by runtime outputs.
    /// </summary>
    [JsonPropertyName("sampleTime")]
    public double SampleTime { get; }

    /// <summary>
    /// Gets the IO address group associated with the trigger.
    /// </summary>
    [JsonPropertyName("addressGroup")]
    public IoAddressGroup AddressGroup { get; }
}
