contract TheGoodsSociety is ERC721, ERC721Enumerable, Ownable {
    /// @notice Mint price in ether units (e.g. 0.04 ETH is 40000000000000000 wei)
    uint256 public MINT_PRICE = 0.04 ether;

    /// @notice Max supply of the The Goods Society
    uint256 public MAX_SUPPLY = 1100;

    /// @notice The base URI; Please remove slash suffix
    string public BASE_URI = "https://gateway.pinata.cloud/ipfs/QmdTqqG1BQ7VnwDGckVMgQaxdKKvrSX4WtHVeokWGqrWe9";

    /// @notice Fee recipient; Multisig address
    address payable public FEE_RECIPIENT = payable(0x772A0c33c39339097D79B8f56c26C2F9C83FfA9e);

    constructor() ERC721("The Goods Society", "GOODS") {}

    /// @notice Set the base URI. This allows us to do endpoint upgrade
    /// @dev Only owner can call this function
    function setBaseURI(string memory uri) external onlyOwner {
        BASE_URI = uri;
    }

    /// @notice Get the base URI
    function getBaseURI() external view returns (string memory) {
        return BASE_URI;
    }

    /// @notice Mint new NFT
    /// @dev Anyone can call this function
    function mint() external payable {
        // Make sure user have sent enough ETH
        require(msg.value >= MINT_PRICE, "!NEETH"); // Not enough ETH

        // Make sure total supply is capped
        require(totalSupply() + 1 <= MAX_SUPPLY, "!OOS"); // Out of stock

        // Mint user the NFT token
        uint256 tokenID = totalSupply() + 1;
        _mint(msg.sender, tokenID);
    }

    /// @notice Mint new NFT to given address
    /// @notice This is free mint
    /// @dev only owner can call this function
    function mintTo(address recipient, uint256 amount) external onlyOwner {
        for (uint256 i = 0; i < amount; i++) {
            require(totalSupply() + 1 <= MAX_SUPPLY, "!OOS"); // Out of stock

            // Mint user the NFT token
            uint256 tokenID = totalSupply() + 1;
            _mint(recipient, tokenID);
        }
    }

    /// @notice Send ETH inside the contract to multisig address
    function withdraw() external {
        (bool success, ) = address(FEE_RECIPIENT).call{ value: address(this).balance }("");
        require(success, "!WF"); // Withdraw failed
    }

    /// @notice Send ETH inside the contract to multisig address
    function withdraw(uint256 amount) external {
        (bool success, ) = address(FEE_RECIPIENT).call{ value: amount }("");
        require(success, "!WF"); // Withdraw failed
    }

    /// @notice Implement interface for ERC721URIStorage
    function tokenURI(uint256 tokenID) public view virtual override returns (string memory) {
        return string(abi.encodePacked(BASE_URI, "/", Strings.toString(tokenID), ".json"));
    }

    /// @notice Setup the hook. This allows us to check wether the NFT is paused or not
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenID
    ) internal override(ERC721, ERC721Enumerable) {
        ERC721Enumerable._beforeTokenTransfer(from, to, tokenID);
    }

    /// @notice Return true if the interfaceID is supported
    function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {
        return ERC721Enumerable.supportsInterface(interfaceId);
    }
}
/// @title The Goods Society
/// @author bayu (github.com/pyk)
/// @dev Token ID start from 1 to 1100
function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {
    return ERC721Enumerable.supportsInterface(interfaceId);
}

/// @notice Return true if the interfaceID is supported