contract ReactGoldPass is ERC721Enumerable, Ownable {

    using Strings for uint256;

   	uint public constant MAX_REACTS = 4096;
    string _baseTokenURI;
    uint256 private _reserved = 16;
    uint256 private _price = 0.256 ether;
    bool public _paused = true;
    uint256 OneOzBAR = 0;

    // withdraw addresses
    address t0 = 0x39c797D1D3655dAe28f24fDDa2e1Fa752C8ecf61;
    address t1 = 0x9cAb92b8aA4C24412A6Df873308Dcb279cDf87B5;
    address t2 = 0x79a6e2F225881677cC3805ff44E2471E38C52A00;
    address t3 = 0x18ecd98188B54111E3041E107636484174599Eba;
    address t4 = 0xF8C4d6F0DFc7eb090389f6d7Ee84F4Fb385DaF19;

    constructor(string memory baseURI) ERC721("ReactGold Pass", "REACT")  {
        setBaseURI(baseURI);

        // team gets the first 5 passes
        _safeMint( t0, 0);
        _safeMint( t1, 1);
        _safeMint( t2, 2);
        _safeMint( t3, 3);
        _safeMint( t4, 4);
    }

	function selectOneOzBAR() public onlyOwner {

        require(OneOzBAR == 0, "OneOzBAR already minted");

        uint256 max = MAX_REACTS - 1;
        uint256 sell = totalSupply() - 1;
        uint256 randomHash = uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty)));

        randomHash = randomHash % max;

        if (randomHash >= 5 && randomHash <= sell){
            OneOzBAR =  randomHash;
        }
    }

    function getOneOzBAR() public view returns (uint256){
        if(msg.sender != owner()){
            require (block.timestamp > 1636607471, "Not yet"); //  November 11, 2021 00:11:11 (am) in time zone America/New York (EST) 
        }
        return OneOzBAR;
    }

    function reserveReactGoldPass(uint256 num) public payable {
        uint256 supply = totalSupply();
        require( !_paused,                              	"Sale paused" );
        require( num < 11,                              	"You can reserve a maximum of 10 Passes" );
        require( supply + num <= MAX_REACTS - _reserved,    "Exceeds maximum Passes supply" );
        require( msg.value >= _price * num,             	"Ether sent is not correct" );

        for(uint256 i; i < num; i++){
            _safeMint( msg.sender, supply + i );
        }
    }

    function walletOfOwner(address _owner) public view returns(uint256[] memory) {
        uint256 tokenCount = balanceOf(_owner);

        uint256[] memory tokensId = new uint256[](tokenCount);
        for(uint256 i; i < tokenCount; i++){
            tokensId[i] = tokenOfOwnerByIndex(_owner, i);
        }
        return tokensId;
    }

    // Just in case Eth does some crazy stuff
    function setPrice(uint256 _newPrice) public onlyOwner() {
        _price = _newPrice;
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return _baseTokenURI;
    }

    function setBaseURI(string memory baseURI) public onlyOwner {
        _baseTokenURI = baseURI;
    }

    function getPrice() public view returns (uint256){
        return _price;
    }

    function giveAway(address _to, uint256 _amount) external onlyOwner() {
        require( _amount <= _reserved, "Exceeds reserved Passes supply" );

        uint256 supply = totalSupply();
        for(uint256 i; i < _amount; i++){
            _safeMint( _to, supply + i );
        }

        _reserved -= _amount;
    }

    function pause(bool val) public onlyOwner {
        _paused = val;
    }

    function withdrawAll() public payable onlyOwner {
        uint256 _each = address(this).balance / 5;
        require(payable(t0).send(_each));
        require(payable(t1).send(_each));
        require(payable(t2).send(_each));
        require(payable(t3).send(_each));
        require(payable(t4).send(_each));
    }
}
function setPrice(uint256 _newPrice) public onlyOwner() {
    _price = _newPrice;
}

// Just in case Eth does some crazy stuff