contract PilatiNFT is ERC721Enumerable, Ownable {

    using Counters for Counters.Counter;
    using Strings for uint256;

    Counters.Counter private _tokenIds;

    mapping(uint256 => string) private _tokenURIs;
    
    uint256 public MAX_PILATIS = 250;
    uint public pilatiPrice = 3.83 ether; // 10,000 GBP
    uint256 public maxMint = 5;

    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {}

    /**
     * @dev Used to mint pilati.
     */
    function mintPilati(address player, string memory newTokenURI)
        public onlyOwner
        returns (uint256)
    {
        require(_tokenIds.current() < MAX_PILATIS,"All Tokens Have been minted");
        _tokenIds.increment();

        uint256 newItemId = _tokenIds.current();
        _mint(player, newItemId);
        _setTokenURI(newItemId, newTokenURI);

        return newItemId;
    }

    /**
     * @dev Used to buy pilati nft using eth.
     */
    function buyPilati(address player, string[] memory newTokenURIS, uint256 _count)
        public payable
        returns (uint256[] memory tokenHashes)
    {
        require(_tokenIds.current() < MAX_PILATIS,"All Tokens Have been minted.");
        require(_tokenIds.current() + _count <= MAX_PILATIS,"Token count exceeds with available NFT's.");
        require(_count <= maxMint,"You have exceeded max mint count.");
        require(msg.value >= pilatiPrice * _count, "Insuffient ETH amount sent.");
        require(newTokenURIS.length == _count, "Token URI's & count does not match.");

        tokenHashes = new uint256[](_count);

        for (uint256 i = 0; i < _count; i++) {
            
            _tokenIds.increment();
            uint256 newItemId = _tokenIds.current();
            _mint(player, newItemId);
            _setTokenURI(newItemId, newTokenURIS[i]);
            tokenHashes[i] = newItemId;

        }
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");

        string memory _tokenURI = _tokenURIs[tokenId];
        string memory base = _baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(base, _tokenURI));
        }

        return super.tokenURI(tokenId);
    }

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
        require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
        _tokenURIs[tokenId] = _tokenURI;
    }

    /**
     * @dev Used to set the max mint limit.
     */
    function setMaxMint(uint256 newMaxMint) external  onlyOwner {
        maxMint = newMaxMint;
    }

    /**
     * @dev Used to set the mint price for 1 nft.
     */
    function setPilatiPrice(uint newPrice) external  onlyOwner {
        pilatiPrice = newPrice;
    }

    /**
     * @dev Used to set the max pilati nft available.
     */
    function setMaxPilaties(uint256 newMaxPilaties) external  onlyOwner {
        MAX_PILATIS = newMaxPilaties;
    }

    /**
     * @dev Used to get the max mint limit.
     * @return uint256 for max mint limit.
     */
    function getMaxMint() public view returns (uint256) {
        return maxMint;
    }

    /**
     * @dev Used to get the price for 1 pilati nft.
     * @return uint256 for pilati price.
     */    
    function getPilatiPrice() public view returns (uint256) {
        return pilatiPrice;
    }

    /**
     * @dev Used to get the max pilaties available limit.
     * @return uint256 for max pilaties available.
     */
    function getMaxPilaties() public view returns (uint256) {
        return MAX_PILATIS;
    }

    /**
     * @dev Used to withdraw the ETH from Contract.
     */
    function withdrawETH() external onlyOwner {
        payable(_msgSender()).transfer(address(this).balance);
    }
    
}
// import "@openzeppelin/contracts/utils/Counters.sol";
// import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
// import "@openzeppelin/contracts/access/Ownable.sol";
function buyPilati(address player, string[] memory newTokenURIS, uint256 _count)
    public payable
    returns (uint256[] memory tokenHashes)
{
    require(_tokenIds.current() < MAX_PILATIS,"All Tokens Have been minted.");
    require(_tokenIds.current() + _count <= MAX_PILATIS,"Token count exceeds with available NFT's.");
    require(_count <= maxMint,"You have exceeded max mint count.");
    require(msg.value >= pilatiPrice * _count, "Insuffient ETH amount sent.");
    require(newTokenURIS.length == _count, "Token URI's & count does not match.");

    tokenHashes = new uint256[](_count);

    for (uint256 i = 0; i < _count; i++) {
            
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
        _mint(player, newItemId);
        _setTokenURI(newItemId, newTokenURIS[i]);
        tokenHashes[i] = newItemId;

    }
}

/**
 * @dev Used to buy pilati nft using eth.
 */