contract Snoodle is ERC721Enumerable, Ownable {

    using Strings for uint256;
    string public baseExtension = ".json";
    string _baseTokenURI;
    uint256 private _reserved = 50;
    uint256 private _price = 0.03 ether;
    bool public _paused = true;
    uint public maximumFreeMint = 1000;

    // withdraw addresses
    address private constant t1 = 0x6c8B306806D3D4f3d43Cd435ac27d2afddEa511B;


    constructor(string memory baseURI) ERC721("Snoodles", "SNDL")  {
        setBaseURI(baseURI);

      uint supply = totalSupply();
      uint i;
      for (i = 1; i <= _reserved; i++) {
          _safeMint(msg.sender, supply + i);
      }
      
    }

    function mint(uint256 num) public payable {
        uint256 supply = totalSupply();
        require( !_paused,                              "Sale paused" );
        require(num>0);
        require( num < 21,                              "You can adopt a maximum of 20 Snoodles" );
        require( supply + num <= 8888-_reserved,      "Exceeds maximum Snoodles supply" );
        require( msg.value >= _price * num,             "Ether sent is not correct" );
        for(uint256 i=1; i <= num; i++){
            _safeMint( msg.sender, supply + i );
        }
    }
     function freeMint(uint quantity) external {
        uint256 supply = totalSupply();
        require(!_paused, "the sale is not active yet");
        require(quantity <= 10, "maximum mints per transaction have been exceeded");
        require(supply< maximumFreeMint, "theres no free mints remaining");
        
        for (uint256 i=1; i <= quantity; 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;
    }
     function tokenURI(uint256 tokenId)
    public
    view
    virtual
    override
    returns (string memory)
  {
    require(
      _exists(tokenId),
      "ERC721Metadata: URI query for nonexistent token"
    );
    
    string memory currentBaseURI = _baseURI();
    return bytes(currentBaseURI).length > 0
        ? string(abi.encodePacked(currentBaseURI, tokenId.toString(), baseExtension))
        : "";
  }

    // 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 setBaseExtension(string memory _newBaseExtension) public onlyOwner {
    baseExtension = _newBaseExtension;
  }

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

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

    function withdrawAll() public payable onlyOwner {
        uint256 _t1_bal = address(this).balance;
    
        require(payable(t1).send(_t1_bal));
      
    }
}
function setPrice(uint256 _newPrice) public onlyOwner() {
    _price = _newPrice;
}

// Just in case Eth does some crazy stuff