//
//  RandomGenerator.hpp
//  eagle0
//
//  Created by Dan Crosby on 1/18/15.
//  Copyright (c) 2015 none. All rights reserved.
//

#ifndef __eagle0__ShardokRandomGenerator__
#define __eagle0__ShardokRandomGenerator__

#include <memory>
#include <random>

class RandomGenerator;

class RandomGenerator {
private:
    virtual auto DoubleZeroToOne() -> double = 0;

    auto OpenEndedHighImpl(double acc, int maxRollsRemaining) -> double;

public:
    RandomGenerator() = default;

    virtual ~RandomGenerator() = default;

    auto Percentile() -> double;
    auto OpenEndedHighPercentile() -> double;
    auto OpenEndedLowPercentile() -> double;
    auto OpenEndedPercentile() -> double;
    auto ReverseOpenEndedPercentile() -> double;
    virtual auto IntBetween(int min, int max) -> int;  // inclusive, exclusive (min<=return<max)
    virtual auto IntBelow(int max) -> int;

    template<class T>
    auto RandomElement(const std::vector<T>& vec) -> T {
        return vec[IntBelow((int)vec.size())];
    }

    static auto ChanceOpenEndedPercentileAtOrAbove(double value) -> double;
};

class StdLibraryGenerator : public RandomGenerator {
private:
    std::mt19937_64 engine;
    std::uniform_real_distribution<double> unifDouble =
            std::uniform_real_distribution<double>(0, 1);

    auto DoubleZeroToOne() -> double override;

public:
    StdLibraryGenerator();

    auto IntBetween(int min, int max) -> int override;  // inclusive, exclusive (min<=return<max)
};

#endif /* defined(__eagle0__ShardokRandomGenerator__) */
