contract VITALIKS is ERC721, Ownable {
    using SafeMath for uint256;

    uint256 public _price = 69000000000000000;

    bool private _paused = true;
    
    address private _giveawayWalletAddress = 0xdBDD145e95447605cc9b3682c5a0A9ad4Fe84064;

    address _withdrawAddress = 0xb6Ae9721b492e59aC6D8b1d138517cFEB554093b;
    
    bool private _reserveMinted = false;

    constructor() ERC721('The Vitaliks', 'VITALIKS') {
        setBaseURI("https://ipfs.io/ipfs/QmX7Xa1Kjci7aGGVjCfsC964b8TNM1ktDFSWj3TKLv9mZZ/");
        mintReserve();
    }

    //MINT x amount of VITALIKS
    function mint(uint256 _num) public payable {
        uint supply = totalSupply();

        require(!_paused, "Minting is currently paused!");
        require(_num < 21, "You can only mint 20 Vitaliks's with each transaction!");
        require(supply + _num < 6968, "Supply exceeded!");

        for(uint i = 0; i < _num; i++) {
            _safeMint(msg.sender, supply+i);
        }
    }

      function mintReserve() private {
        require(!_reserveMinted, "Reserve has already been minted");
        uint supply = totalSupply();

        for(uint i = 0; i < 100; i++) {
            _safeMint(0xdBDD145e95447605cc9b3682c5a0A9ad4Fe84064, supply+i);
        }
        _reserveMinted = true;
    }

    //CHANGE PAUSE STATE
    function pause(bool _value) public onlyOwner {
        _paused = _value;
    }


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


    //RETURN ALL TOKENS OF A SPECIFIC ADDRESS
    function walletOfOwner(address _owner) external view
    returns (uint256[] memory)
    {
        uint256 tokenCount = balanceOf(_owner);

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

        return tokensId;
    }

    //RETURNS THE AMOUNT OF TOKES THAT HAVE BEEN MINTED ALREADY
    function returnSupply() external view returns (uint256) {
        return totalSupply();
    }

    //WITHDRAW CONTRACT BALANCE TO DEFINED ADDRESS
    function withdraw() public onlyOwner {
        uint balance = address(this).balance;
        payable(_withdrawAddress).transfer(balance);
    }

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

}
//TODO
// CHANGE WITHDRAW ADDRESS
function pause(bool _value) public onlyOwner {
    _paused = _value;
}

//CHANGE PAUSE STATE