contract PickleAnniversary is ERC721Enumerable, Ownable {
    string public _tokenURI;
    uint256 public snapshotTime = 1631248201;
    bool public _ownerClaimed;
    mapping(address => bool) public userClaimed;
    mapping(uint256 => bool) public giftRedeemed;

    IFeeDistributor public constant DILL = IFeeDistributor(
        0x74C6CadE3eF61d64dcc9b97490d9FbB231e4BdCc
    );

    constructor(string memory _uri)
        public
        ERC721("Pickle Anniversary Gift", "P1CKLE")
    {
        _tokenURI = _uri;
        _ownerClaimed = false;
    }

    // Reserver 25 mints for the team to distribute
    function reserveMints() public onlyOwner {
        require(_ownerClaimed = false, "Owner has already claimed");
        uint256 supply = totalSupply();
        uint256 i;
        for (i = 0; i < 25; i++) {
            _safeMint(msg.sender, supply + i);
        }
        _ownerClaimed = true;
    }

    function tokenURI(uint256 _tokenId)
        public
        override
        view
        returns (string memory)
    {
        require(
            _exists(_tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );

        string memory uri = _baseURI();
        return uri;
    }

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

    function setTokenURI(string memory _uri) public onlyOwner {
        _tokenURI = _uri;
    }

    function mintNFT(address recipient) public returns (uint256) {
        require(!userClaimed[msg.sender], "User has already claimed NFT");

        // Require a DILL balance > 10 at the snapshotTime
        require(
            DILL.ve_for_at(msg.sender, snapshotTime) >= mul(10, 1e18),
            "User balance does not qualify"
        );

        uint256 supply = totalSupply();
        uint256 newItemId = supply;
        _mint(recipient, newItemId);

        userClaimed[msg.sender] = true;

        return newItemId;
    }

    function redeemGift(uint256 tokenId) public returns (bool) {
        require(
            msg.sender == ownerOf(tokenId),
            "Can only redeem tokens you own"
        );
        require(
            giftRedeemed[tokenId] == false,
            "Token has already been redeemed"
        );
        giftRedeemed[tokenId] = true;
        return true;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }
}
function reserveMints() public onlyOwner {
    require(_ownerClaimed = false, "Owner has already claimed");
    uint256 supply = totalSupply();
    uint256 i;
    for (i = 0; i < 25; i++) {
        _safeMint(msg.sender, supply + i);
    }
    _ownerClaimed = true;
}

// Reserver 25 mints for the team to distribute