contract OCMRandomizer is VRFConsumerBase, Ownable {
    using Strings for uint256;
    bytes32 internal keyHash;
    uint256 internal fee;
    
    uint256[] public randomResults; // track all random numbers, first random number is used for Desserts
    uint256 public counter = 0;     // counter of random numbers generated
    uint256 public offset;          // offset of Desserts, set once and locked after first random number

    event RandomRequested(bytes32 indexed requestId, address indexed requester);
    event RandomFullfilled(bytes32 indexed requestId, uint256 indexed result);

    /**
     * Constructor inherits VRFConsumerBase
     * 
     * Network: Kovan
     * Chainlink VRF Coordinator address: 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9
     * LINK token address:                0xa36085F69e2889c224210F603D836748e7dC0088
     * Key Hash: 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4
     * Request testnet LINK and ETH here: https://faucets.chain.link/
     *
     * retreived from: https://docs.chain.link/docs/vrf-contracts/
     * Network: Mainnet
     * LINK Token  0x514910771AF9Ca656af840dff83E8264EcF986CA
     * VRF Coordinator  0xf0d54349aDdcf704F77AE15b96510dEA15cb7952
     * Key Hash  0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445
     */
    constructor() 
        VRFConsumerBase(
            0xf0d54349aDdcf704F77AE15b96510dEA15cb7952, // VRF Coordinator
            0x514910771AF9Ca656af840dff83E8264EcF986CA  // LINK Token
        )
    {
        keyHash = 0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445;
        fee = 2 * 10 ** 18; // 2 LINK (Varies by network)
    }
    
    /** 
     * Requests randomness, first call is used for Desserts 
     */
    function getRandomNumber() external onlyOwner returns (bytes32 requestId) {
        require(block.number > 14181581, "Not time yet");
        require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK");
        requestId = requestRandomness(keyHash, fee);
        emit RandomRequested(requestId, msg.sender);
        return requestId;
    }

    //
    // Dessert distribution for each OCM# (j)
    //
    // If offset is 0, 15 Dessert3s at j = 364, 1301, 1453, 1527, 1601, 1629, 2214, 4097, 5227, 5956, 6694, 6754, 7442, 9132, 9850
    // Overall distribution of Desserts is 15 Dessert3, 4485 Dessert2, 5500 Dessert1
    //
    function dessert(uint256 j) public view returns (uint256) {
        require(counter > 0, "Dessert not served");
        require(j>0 && j<10001, 'error');
        j = (j + offset) % 10000; // this is the fair and random offset from the VRF
        uint256 r = (uint256(keccak256(abi.encode(j.toString())))) % 10000; // this is the fixed sequence with the desired rarity distribution
        if (r < 8) {
            return 3; // Dessert3
        } else if (r >= 5538) {
            return 2; // Dessert2
        } else {
            return 1; // Dessert1
        }
    }    

    /**
     * Callback function used by VRF Coordinator
     */
    function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
        randomResults.push(randomness);
        if (counter == 0) {
            offset = randomness % 10000; // There is very minor bias in ideal uniform probability distribution because randomness 2**256 % 10000 != 0
        }
        counter++; // Counter could wrap around to 2**256 in theory, but not in practice
        emit RandomFullfilled(requestId, randomness);        
    }

    // Withdraw function to avoid locking LINK in the contract
    function withdrawLink() external onlyOwner {
        LINK.transfer(owner(), LINK.balanceOf(address(this)));
    }
}
//
// Use ChainLink's VRF to distribute the Desserts for OnChainMonkey
//
// First call sets the Desserts
// Later calls to the VRF generate random numbers to be used in future features
//
function withdrawLink() external onlyOwner {
    LINK.transfer(owner(), LINK.balanceOf(address(this)));
}

// Withdraw function to avoid locking LINK in the contract