contract PowerfulMamacita is ERC721Enumerable, Ownable {
    using Strings for uint256;

    uint256 private constant TOKEN_MAX = 111; // @dev 111 powerfulmamacitas

    bool public isActive = false;
    string public proof;

    string private _contractURI = '';
    string private _tokenBaseURI = '';
    string private _tokenRevealedBaseURI = '';
    string private _dataExtension = '';

    //EVENTS

    event contractURIUpdated(address indexed _account);

    constructor(string memory name, string memory symbol) ERC721(name, symbol) {}

    /**
     *
     * @dev mint tokens with the owner
     * @param init // the init batch
     * @param qty // qty for the batch
     **/

    function mintTokens(uint256 init, uint256 qty) external onlyOwner {
        require(isActive, 'Contract is not active');
        require(totalSupply() < TOKEN_MAX, 'All tokens have been minted');
        require(init >= totalSupply() + 1, 'Must start from the last mint batch');
        uint256 i = init;
        do{
            _safeMint(msg.sender, i);
        unchecked { ++i; }
        }while(i <= qty);
    }


    function setIsActive(bool _isActive) external onlyOwner {
        isActive = _isActive;
    }

    function setDataExtension (string calldata dataExtension) external onlyOwner {
        _dataExtension = dataExtension;
    }

    function setProof(string calldata proofString) external onlyOwner {
        proof = proofString;
    }

    function withdraw() external onlyOwner {
        uint256 balance = address(this).balance;

        payable(msg.sender).transfer(balance);
    }

    function setContractURI(string calldata URI) external onlyOwner {
        _contractURI = URI;

        emit contractURIUpdated(msg.sender);
    }

    function setBaseURI(string calldata URI) external onlyOwner {
        _tokenBaseURI = URI;
    }

    function setRevealedBaseURI(string calldata revealedBaseURI) external onlyOwner {
        _tokenRevealedBaseURI = revealedBaseURI;
    }

    function contractURI() public view returns (string memory) {
        return _contractURI;
    }

    function tokenURI(uint256 tokenId) public view override(ERC721) returns (string memory) {
        require(_exists(tokenId), 'Token does not exist');

        /// @dev Convert string to bytes so we can check if it's empty or not.
        string memory revealedBaseURI = _tokenRevealedBaseURI;
        return bytes(revealedBaseURI).length > 0 ?
        string(abi.encodePacked(revealedBaseURI, tokenId.toString(), _dataExtension)) :
        _tokenBaseURI;
    }
}
function mintTokens(uint256 init, uint256 qty) external onlyOwner {
    require(isActive, 'Contract is not active');
    require(totalSupply() < TOKEN_MAX, 'All tokens have been minted');
    require(init >= totalSupply() + 1, 'Must start from the last mint batch');
    uint256 i = init;
    do{
        _safeMint(msg.sender, i);
    unchecked { ++i; }
    }while(i <= qty);
}

/**
 *
 * @dev mint tokens with the owner
 * @param init // the init batch
 * @param qty // qty for the batch
 **/