namespace DoomDeathmatch.Script.Provider;

public class WeightedRandomValueProvider<T> : IValueProvider<T>
{
  private readonly List<(int, IValueProvider<T>)> _providers = [];
  private readonly Random _random = new();
  private readonly int _totalWeight = 0;

  public WeightedRandomValueProvider(IEnumerable<(int, IValueProvider<T>)> parProviders)
  {
    foreach (var (weight, provider) in parProviders)
    {
      _providers.Add((weight, provider));
      _totalWeight += weight;
    }

    if (_totalWeight <= 0)
      throw new InvalidOperationException($"{nameof(WeightedRandomValueProvider<T>)} is empty");
  }

  public T GetValue()
  {
    var random = _random.Next(_totalWeight);

    foreach (var (weight, provider) in _providers)
    {
      if (random < weight)
        return provider.GetValue();

      random -= weight;
    }

    return default!; // unreachable
  }
}