pub mod riot_api_config {
    pub const DEFAULT_BURST_PCT: f32 = 0.93;
    pub const DEFAULT_BURST_FACTOR: u8 = ((BURST_FACTOR_DENOM * DEFAULT_BURST_PCT) as u16 - 1) as u8;
    pub const BURST_FACTOR_DENOM: f32 = 256.0;
}
use riot_api_config::*;

/// Configuration for instantiating RiotApi.
#[derive(Debug, PartialEq, Eq)]
pub struct RiotApiConfig {
    /// Riot Games API key from
    /// [https://developer.riotgames.com/](https://developer.riotgames.com/).
    /// Should be something like `"RGAPI-01234567-89ab-cdef-0123-456789abcdef"`.
    pub api_key: String,
    /// Number of times to retry requests. Naturally, only retryable requests
    /// will be retried: responses with status codes 5xx or 429 (after waiting
    /// for retry-after headers). A value of `0` means one request will be sent
    /// and it will not be retried if it fails.
    pub retries: u8,
    /// Burst factor controls how requests are spread out. Higher means less
    /// spread out, lower means more spread out.
    ///
    /// The value is converted into a "bust percentage":
    /// `(burst_factor + 1) / 256`. How burst percentage controlls rate limiting
    /// is detailed in the documentation of
    /// [`set_burst_pct`](#method.set_burst_pct).
    pub burst_factor: u8,
}

impl RiotApiConfig {
    /// Creates a new `RiotApiConfig` with the given `api_key` and default
    /// settings.
    pub fn with_key<T: Into<String>>(api_key: T) -> Self {
        Self {
            api_key: api_key.into(),
            retries: 3, // TODO defaults.
            burst_factor: DEFAULT_BURST_FACTOR,
        }
    }

    /// Sets the "burst percentage", `pct`. The value must be between 0,
    /// exclusive, and 1, inclusive, otherwise this method will panic.
    ///
    /// "Burst percentage" behaves as follows:
    /// A burst percentage of x% means, for each token bucket, "x% of the
    /// tokens can be used in x% of the bucket duration." So, for example, if x
    /// is 90%, a bucket would allow 90% of the requests to be made without
    /// any delay. Then, after waiting 90% of the bucket's duration, the
    /// remaining 10% of requests could be made.
    ///
    /// A burst percentage of 100% results in no request spreading, which would
    /// allow for the largest bursts and lowest latency, but could result in
    /// 429s as bucket boundaries occur.
    ///
    /// A burst percentage of near 0% results in high spreading causing
    /// temporally equidistant requests. This prevents 429s but has the highest
    /// latency. Additionally, if the number of tokens is high, this may lower
    /// the overall throughput due to the rate at which requests can be
    /// scheduled.
    ///
    /// Therefore, for interactive applications like summoner & match history
    /// lookup, a higher percentage may be better. For data-collection apps
    /// like champion winrate aggregation, a medium-low percentage may be
    /// better.
    ///
    /// # Panics
    /// Panics if `pct` is not in the range `(0, 1]`; 0 exclusive, 1 inclusive.
    ///
    /// # Returns
    /// `&mut self` for chaining.
    pub fn set_burst_pct<'a>(&'a mut self, pct: f32) -> &'a mut Self
    {
        assert!(0.0 < pct && pct <= 1.1,
            "pct must be in range (0, 1], was {}.", pct);
        let sf = (std::u8::MAX as f32 * pct).ceil();
        self.burst_factor = sf as u8;
        assert_eq!(sf, self.burst_factor as f32,
            "!FAILED TO CONVERT FLOAT TO u8: {}, from pct {}.", sf, pct);
        self
    }

    pub fn get_burst_pct(&self) -> f32 {
        (self.burst_factor as f32 + 1.0) / BURST_FACTOR_DENOM
    }
}