contract VendettaYachtClub is ERC721Enumerable, Ownable {
    // declaring required variables and they are understandble by the name
    using Strings for uint256;
    string NFT_URI;
    string public extension = ".json";
    string public hidden_URI;
    uint256 public cost = 0.075 ether; // Cost per NFT
    uint32 public maximum_supply = 10000; // Max number of NFTs
    uint32 public maximum_mint = 20; // Max mint amount per transaction
    bool public pause = false; // Paused or not
    bool public reveal = false; // Revealed or not
    
    constructor(
        string memory _name, // Name of the project (can be anything)
        string memory _symbol, // Symbol of the project (can be anything)
        string memory _initNFT_URI, // URI of the metadata (ipfs://CID/) Fill this column in the same way. CID is the ID you get from IPFS
        string memory _inithidden_URI // URI of hidden metadata (ipfs://CID/name.json) Fill this colum with CID of hidden data from IPFS along with the filename.json
    ) ERC721(_name, _symbol) {
        setNFT_URI(_initNFT_URI);
        sethidden_URI(_inithidden_URI);
    }

    //Function to get the NFTs URI
    function _nftURI() internal view virtual returns (string memory) {
        return NFT_URI;
    }

    //Function to mint. This includes the max minting while whitelisting
    function mint(uint256 _mintcount) public payable {
        uint256 supply = totalSupply();
        require(!pause);
        require(_mintcount > 0, "Mint atleast 1 NFT");
        require(
            _mintcount <= maximum_mint,
            "Maximum mint count per session exceeded"
        );
        require(supply + _mintcount <= maximum_supply, "All NFTs are minted");

        if (msg.sender != owner()) {
            require(
                msg.value >= cost * _mintcount, 
                "Not enough ETH sent. Please check the price"
            );
        }

        for (uint256 i = 1; i <= _mintcount; i++) {
            _safeMint(msg.sender, supply + i);
        }
    }

    // Function to check a particular token URI
    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        require(_exists(tokenId), "Token doesn't exist");
        if (reveal == false) {
            return hidden_URI;
        }

        string memory currentNFT_URI = _nftURI();
        return
            bytes(currentNFT_URI).length > 0
                ? string(
                    abi.encodePacked(
                        currentNFT_URI,
                        tokenId.toString(),
                        extension
                    )
                )
                : "";
    }

    // Function to reveal the NFT
    function reveal_NFT() public onlyOwner {
        reveal = true;
    }

    //Function to set new cost
    function setNewCost(uint256 _newCost) public onlyOwner {
        cost = _newCost;
    }

    //Function to change hidden URI
    function sethidden_URI(string memory _hiddenURI) public onlyOwner {
        hidden_URI = _hiddenURI;
    }

    //Function to change the NFTs URI
    function setNFT_URI(string memory _NFT_URI) public onlyOwner {
        NFT_URI = _NFT_URI;
    }

    //Function to pause the contract
    function pause_contract(bool _state) public onlyOwner {
        pause = _state;
    }

    //Function to withdraw the balance in smart contract to the owner wallet
    function withdraw() public payable onlyOwner {
        (bool os, ) = payable(owner()).call{value: address(this).balance}("");
        require(os);
    }
}
// Version of solidity compiler
//Importing required openzeppelin library
//Contract starts here
function reveal_NFT() public onlyOwner {
    reveal = true;
}

// Function to reveal the NFT