namespace ConeCalorimeter.Services;

internal static class ModbusFloatSelector
{
    private static readonly ModbusFloatByteOrder[] AlternateFloatByteOrders =
    [
        ModbusFloatByteOrder.Cdab,
        ModbusFloatByteOrder.Badc,
        ModbusFloatByteOrder.Dcba
    ];

    public static bool TrySelectRangedFloat(
        ModbusFloatReadResult result,
        double minimum,
        double maximum,
        out ModbusFloatByteOrder byteOrder,
        out double value,
        out int matchCount)
    {
        var alternateMatches = AlternateFloatByteOrders
            .Where(candidate => IsInRange(result.GetValue(candidate), minimum, maximum))
            .ToArray();
        var isAbcdInRange = IsInRange(result.Abcd, minimum, maximum);

        matchCount = alternateMatches.Length + (isAbcdInRange ? 1 : 0);

        if (isAbcdInRange)
        {
            byteOrder = ModbusFloatByteOrder.Abcd;
            value = result.Abcd;
            return true;
        }

        if (alternateMatches.Length != 1)
        {
            byteOrder = default;
            value = double.NaN;
            return false;
        }

        byteOrder = alternateMatches[0];
        value = result.GetValue(byteOrder);
        return true;
    }

    public static bool IsInRange(double value, double minimum, double maximum)
    {
        return double.IsFinite(value) && value >= minimum && value <= maximum;
    }
}
