contract FuzzyFoxes is ERC721URIStorage, Ownable{
 
    using Strings for uint256;
    
    uint256 public totalFoxes;
    uint256 public totalCount = 10000; // max supply of 10000 foxes
    uint256 public maxMintAmount = 20; //max minting 20 foxes per tx
    uint256 public price = 0.05 ether; // 0.06 ether / mint, 0.05 in presale
    string public baseURI;
    string public baseExtension=".json";
    string public notRevealedURI;
    bool public paused = false;
    bool public revealed = false;

    constructor(string memory name_, string memory symbol_, string memory initbaseURI_, string memory initNotRevealedURI_) ERC721(name_, symbol_) {
        setBaseURI(initbaseURI_);
        setRevealedURI(initNotRevealedURI_);
    }
    
    function mint(address _to, uint256 _mintAmount) public payable {
        require(!paused, "Sale is not active yet");
        require(_mintAmount >0 && _mintAmount <= maxMintAmount, "Select between 1 and 20 foxes to mint.");
        require(totalFoxes + _mintAmount <= totalCount, "There aren't that many foxes left!");
        if (msg.sender != owner()){
        require(msg.value >= price * _mintAmount);
        }
        for(uint256 i=1; i<= _mintAmount; i++){
            _safeMint(_to, 1 + totalFoxes++);
        }
    }
    
    function _totalSupply() internal view returns (uint256){
        return totalFoxes;
    }
    function _baseURI() internal view virtual override returns (string memory){
        return baseURI;
    }
 
    //only owner
    function setBaseURI(string memory _newURI) public onlyOwner {
        baseURI = _newURI;
    }
    
    function setRevealedURI(string memory _notRevealedURI) public onlyOwner {
        notRevealedURI = _notRevealedURI;
    }
    
    function reveal() public onlyOwner{
        revealed=true;
    }
 
    function setBaseExtension(string memory _newBaseExtension) public onlyOwner {
        baseExtension = _newBaseExtension;
    }
    function changePrice(uint256 _newPrice) public onlyOwner {
        price = _newPrice;
    }
    function setmaxMintAmount(uint256 _newmaxMintAmount) public onlyOwner {
        maxMintAmount = _newmaxMintAmount;
    }
 
    function setSale(bool _start) public onlyOwner {
        paused = _start;
    }
    function withdraw() public payable onlyOwner {
        require(payable(msg.sender).send(address(this).balance));
    }

    function tokenURI(uint256 tokenId)public view virtual override returns (string memory){
        require(_exists(tokenId),"ERC721Metadata: Token doesn't exsist");
        if (revealed == false) {
            return notRevealedURI;
        }

        string memory currentBaseURI = _baseURI();
        return bytes(currentBaseURI).length>0 ? string(abi.encodePacked(currentBaseURI,tokenId.toString(), baseExtension)) :"";
    }
}
/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
function setBaseURI(string memory _newURI) public onlyOwner {
    baseURI = _newURI;
}

//only owner