contract MferMadness is ERC721, ERC721Enumerable, Ownable {
    bool public saleIsActive = false;
    uint public maxSupply = 64;
    uint public maxTokenOwnership = 2;

    uint256 public minPrice = 0.25 ether;

    string private _baseURIextended;
    bytes32 private _hashOfRandomDraw = 0x0;

    constructor() ERC721("hoodie mfer madness", "MFERMADNESS") {}

    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC721Enumerable) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

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

    function mint(uint numberOfTokens) public payable {
        require(saleIsActive, "Sale must be active to mint tokens");
        require(numberOfTokens <= maxTokenOwnership, "Exceeded max token purchase");
        require(totalSupply() + numberOfTokens <= maxSupply, "Purchase would exceed max supply of tokens");
        require(balanceOf(msg.sender) + numberOfTokens <= maxTokenOwnership, "Purchase would exceed max token ownership");
        require(minPrice * numberOfTokens <= msg.value, "Ether value sent is not correct");

        for(uint i = 0; i < numberOfTokens; i++) {
            uint mintIndex = totalSupply();
            if (totalSupply() < maxSupply) {
                _safeMint(owner(), mintIndex);
                _transfer(owner(), msg.sender, mintIndex);
            }
        }
    }

    function getSHA256HashOfRandomDraw() external view returns (bytes32) {
        return _hashOfRandomDraw;
    }

    /* Owner Functions */

    function setBaseURI(string memory baseURI_) external onlyOwner() {
        _baseURIextended = baseURI_;
    }

    function setSaleState(bool newState) external onlyOwner {
        saleIsActive = newState;
    }

    function setSHA256HashOfRandomDraw(bytes32 newHash) external onlyOwner {
        _hashOfRandomDraw = newHash;
    }

    function reserve(uint numberOfTokens) external onlyOwner {
        uint supply = totalSupply();
        uint i;
        for (i = 0; i < numberOfTokens; i++) {
            _safeMint(msg.sender, supply + i);
        }
    }

    function setMaxTokenOwnership(uint newMaxTokenOwnership) external onlyOwner {
        maxTokenOwnership = newMaxTokenOwnership;
    }

    function setMaxSupply(uint newMaxSupply) external onlyOwner {
        maxSupply = newMaxSupply;
    }

    function setMinPrice(uint256 newMinPrice) external onlyOwner {
        minPrice = newMinPrice;
    }

    function withdraw(address payable to) external onlyOwner {
        uint256 balance = address(this).balance;
        Address.sendValue(to, balance);
    }

}
function setBaseURI(string memory baseURI_) external onlyOwner() {
    _baseURIextended = baseURI_;
}

/* Owner Functions */