namespace VRio.Core.Protocol;

/// <summary>Flash mode for a lighted button (lamp-state bits 0–1).</summary>
public enum LampFlash : byte
{
    Solid = 0,
    FlashSlow = 1,
    FlashMed = 2,
    FlashFast = 3,
}

/// <summary>Brightness level decoded from a lamp-state byte.</summary>
public enum LampBrightness
{
    Off,
    Dim,
    Bright,
}

/// <summary>
/// The <c>state</c> byte of a <see cref="RioCommand.LampRequest"/>: flash bits
/// 0–1 plus two brightness fields (bits 2–3 and 4–5). vRIO decodes it to shade
/// its on-screen lamps the way the physical board would light them.
/// </summary>
public static class RioLampState
{
    /// <summary>Lamp off (SolidOff, 0x00).</summary>
    public const byte SolidOff = 0x00;

    /// <summary>Dim solid (SolidDim, 0x14) — RIOJoy's idle state for mapped lamps.</summary>
    public const byte SolidDim = 0x14;

    /// <summary>Bright solid (SolidBright, 0x3C) — RIOJoy's pressed state.</summary>
    public const byte SolidBright = 0x3C;

    /// <summary>Flash mode from a lamp-state byte.</summary>
    public static LampFlash Flash(byte state) => (LampFlash)(state & 0x03);

    /// <summary>
    /// Effective brightness from a lamp-state byte: the brighter of the two
    /// brightness fields (field 1 = bits 2–3: 0x04 dim / 0x0C bright; field 2 =
    /// bits 4–5: 0x10 dim / 0x30 bright).
    /// </summary>
    public static LampBrightness Brightness(byte state)
    {
        int f1 = state & 0x0C;
        int f2 = state & 0x30;
        bool bright = f1 == 0x0C || f2 == 0x30;
        bool dim = f1 != 0 || f2 != 0;
        return bright ? LampBrightness.Bright : dim ? LampBrightness.Dim : LampBrightness.Off;
    }

    /// <summary>Human-readable description, e.g. <c>"Bright"</c> or <c>"Dim flash-fast"</c>.</summary>
    public static string Describe(byte state)
    {
        LampBrightness b = Brightness(state);
        LampFlash f = Flash(state);
        return f == LampFlash.Solid ? b.ToString() : $"{b} {f}";
    }
}
