namespace Common.Extensions;

public static class EnumerableExtensions
{
  public static double Median(this IEnumerable<double> values)
  {
    var tValues = values.OrderBy(v => v).ToArray();
    if (!tValues.Any())
    {
      throw new ArgumentException(
        "The list must contain at least one value for calculating the median");
    }

    if (tValues.Length % 2 != 0)
    {
      return tValues[tValues.Length / 2];
    }

    var center = tValues.Length / 2;
    return (tValues[center - 1] + tValues[center]) / 2.0;
  }

  public static double Median(this IEnumerable<double> values, out double deviation)
  {
    var tValues = values.ToArray();
    var median = tValues.Median();
    deviation = tValues.Select(value => Math.Abs(value - median)).Median();
    return median;
  }

  public static double Average(this IEnumerable<double> values, out double deviation)
  {
    var tValues = values?.ToArray();
    if (tValues is null || tValues.Length < 2)
    {
      throw new ArgumentException(
        "The list must contain at least two values for calculating standard deviation");
    }

    var average = tValues.Average();

    var diffSquaredSum = tValues.Sum(value => Math.Pow(value - average, 2));
    deviation = Math.Sqrt(diffSquaredSum / (tValues.Length - 1));

    return average;
  }
}
