contract VRFBase is VRFConsumerBase, Ownable {
    bytes32 private immutable keyHash;
    uint256 private immutable fee;

    uint256 public randomSeed;

    constructor(
        bytes32 keyHash_,
        uint256 fee_,
        address vrfCoordinator_,
        address link_
    ) VRFConsumerBase(vrfCoordinator_, link_) {
        keyHash = keyHash_;
        fee = fee_;
    }

    /* ------------- Owner ------------- */

    function requestRandomSeed() external payable virtual onlyOwner whenRandomSeedUnset {
        requestRandomness(keyHash, fee);
    }

    // this function should not be needed and is just an emergency fail-safe if
    // for some reason chainlink is not able to fulfill the randomness callback
    function forceFulfillRandomness() external payable virtual onlyOwner whenRandomSeedUnset {
        randomSeed = uint256(blockhash(block.number - 1));
    }

    /* ------------- Internal ------------- */

    function fulfillRandomness(bytes32, uint256 randomNumber) internal virtual override {
        randomSeed = randomNumber;
    }

    function _shiftRandomSeed(uint256 randomNumber) internal {
        randomSeed = uint256(keccak256(abi.encode(randomSeed, randomNumber)));
    }

    /* ------------- View ------------- */

    function randomSeedSet() public view returns (bool) {
        return randomSeed > 0;
    }

    /* ------------- Modifier ------------- */

    modifier whenRandomSeedSet() {
        if (!randomSeedSet()) revert RandomSeedNotSet();
        _;
    }

    modifier whenRandomSeedUnset() {
        if (randomSeedSet()) revert RandomSeedAlreadySet();
        _;
    }
}
function requestRandomSeed() external payable virtual onlyOwner whenRandomSeedUnset {
        requestRandomness(keyHash, fee);
    }
/* ------------- Owner ------------- */