#ifndef MY_RANDOM_HPP
#define MY_RANDOM_HPP

#include <vector>
#include <random>

/* For spawning a truck, we would like to have a system where they mostly come from a lane.
 *  However, that would be too predictable.
 *  For this reason we implement our own distribution of probabilities,
 *   where they scew to both sides.
 *  Very roughly this:
 *       ..     ..
 *    .-`  `-.-`  `-.
 */
class RadicalNumberGenerator {
  public:
    const int range_max = 100;
  private:
    std::mt19937 gen;
    std::discrete_distribution<> dist;

    /* To achieve the desired form,
     *  we use the sum of 2 normal distributions.
     */
    double normal_probability_density_function(double x, double mean, double variance) {
        return (1 / sqrt(2*M_PI*pow(variance, 2)))
             * exp(-0.5 * (pow(x-mean, 2) / (2*pow(variance, 2))))
        ;
    }

    double radical_probability_density_function(double x) {
        double variance = 6.8d;
        
        return normal_probability_density_function(x, range_max * 0.2, variance)
             + normal_probability_density_function(x, range_max - (range_max * 0.2), variance);
    }

  public:
    RadicalNumberGenerator(int seed) : gen(seed) {
        std::vector<double> probabilities(range_max);
        for (int i = 0; i < range_max; i++) {
            probabilities[i] = std::max(
                0.0,
                radical_probability_density_function((double)i)
            );
        }

         dist = std::discrete_distribution(probabilities.begin(), probabilities.end());
    }

    double operator()(void) {
        return dist(gen);
    }

} radical_number_generator(rand());


/* We would like to spawn enemies and trucks at semi-random intervals,
 *  without too much RNG involved.
 */
class Spawner {
  public:
    int last_blaze = 0;
    int min_distance;
    int denominator;

    void reset() {
        last_blaze = 0;
    }

    bool blaze(int current_distance) {
        if ((current_distance - last_blaze) > min_distance
        &&  rand() % denominator) {
            last_blaze = current_distance;
            return true;
        }

        return false;
    }
};

#endif