contract dogeIncubator is Ownable, IERC1155Receiver, VRFConsumerBase {
    using SafeMath for uint256;
    
    bytes2[] public availableDoges;
    
    uint256 public nftid;
    address public eggAddress;
    address public crackedEggAddress;
    uint256 public crackedEggId;
    address public dogeAddress;
    bool public active = false;
    
    
    uint public contractNumber = 0;
    
    bytes32 internal keyHash;
    bytes32 public currentRequestId;
    
    event Request(bytes32 requestId);
    event DogeBirth(bytes2 dogeType, uint256 pickedIndex);

    /*
        Chainlink VRF:
        LINK	0x514910771AF9Ca656af840dff83E8264EcF986CA
        VRF Coordinator	0xf0d54349aDdcf704F77AE15b96510dEA15cb7952
        Key Hash	0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445
        Fee	2 LINK
    */
    
    uint256 linkFee = 2 ether;
    
    // requestId => hatcher address
    mapping (bytes32 => address) private eggHatcher;
    
    constructor(address _eggAddress, uint256 _eggid, address _crackedEggAddress, uint256 _crackedEggId, address _dogeAddress) VRFConsumerBase(0xf0d54349aDdcf704F77AE15b96510dEA15cb7952, 0x514910771AF9Ca656af840dff83E8264EcF986CA) {
        eggAddress = _eggAddress;
        nftid = _eggid;
        crackedEggAddress = _crackedEggAddress;
        crackedEggId = _crackedEggId;
        dogeAddress = _dogeAddress;
        keyHash = 0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445;
    }
    
    function hatchEgg() public {
        require(active == true, "The incubator is currently disabled");
        
        // send user's eggs to this address
        IERC1155(eggAddress).safeTransferFrom(msg.sender, address(this), nftid, 1, "");
        
        // send the user a cracked egg
        IERC1155(crackedEggAddress).safeTransferFrom(address(this), msg.sender, crackedEggId, 1, "");
        
        currentRequestId = requestRandomness(keyHash, linkFee);
        
        eggHatcher[currentRequestId] = msg.sender;
        
        emit Request(currentRequestId);
        
    }
    
    function finishHatchingEgg(bytes32 requestId, uint256 randomNumber) private {
        
        require(availableDoges.length >= 1, "No more doges");
        
        uint256 randomDoge = 0;
        
        if(availableDoges.length > 1) {
            randomDoge = randomNumber % (availableDoges.length-1);
        }
        
        
        bytes2 pickedDoge = availableDoges[randomDoge];
        availableDoges[randomDoge] = availableDoges[availableDoges.length - 1];
        availableDoges.pop();
        
        emit DogeBirth(pickedDoge, randomDoge);
        
        uint256 pickedDogeId = MoonDoge(dogeAddress).tokenIdByTraits(pickedDoge);
        
        address hatcher = eggHatcher[requestId];
        MoonDoge(dogeAddress).mint(hatcher, pickedDogeId, 1, "");
        
    }
    
    function setActive(bool isActive) public onlyOwner {
        active = isActive;
    }
    
    function addAvailableDoges(bytes2[] memory doges, uint256[] memory amounts) public onlyOwner {
        for (uint256 i = 0; i < doges.length; i++) {
            for (uint256 j = 0; j < amounts[i]; j++) {
                availableDoges.push(doges[i]);
            }
        }
    }
    
    function removeAvailableDoges(bool confirm) public onlyOwner {
        require(confirm == true, "You need to confirm");
        delete availableDoges;
    }
    
    function withdrawCrackedEggs(address to) public onlyOwner {
        uint256 amount = IERC1155(crackedEggAddress).balanceOf(address(this), crackedEggId);
        IERC1155(crackedEggAddress).safeTransferFrom(address(this), to, crackedEggId, amount, "");
    }
    
    function withdrawEther(address payable to, uint256 amount) public onlyOwner {
        to.transfer(amount);
    }

    function withdrawTokens(address token, address to, uint256 amount) public onlyOwner {
        IERC20 token = IERC20(token);
        token.transfer(to, amount);
    }
    
    function onERC1155Received(address operator, address from, uint256 id, uint256 value, bytes calldata data) external override returns(bytes4) {
        return bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"));
    }
    
    function onERC1155BatchReceived(address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external override returns(bytes4) {
        return bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"));
    }
    
    
    /// @dev Called by Chainlink VRF random number provider.
    function fulfillRandomness(bytes32 requestId, uint randomness) internal override {
        require(requestId == currentRequestId, "The requestId is invalid.");
        
        finishHatchingEgg(requestId, randomness);
    }
  
    
}
function fulfillRandomness(bytes32 requestId, uint randomness) internal override {
    require(requestId == currentRequestId, "The requestId is invalid.");
        
    finishHatchingEgg(requestId, randomness);
}

/// @dev Called by Chainlink VRF random number provider.