contract NostalgicApes is ERC721Enumerable, Whitelist {
    using SafeMath for uint256;
    
    uint256 public constant MAX_SUPPLY = 10000;

    string private _baseTokenURI = "ipfs://QmchYHgc4p5pw6jDk9pi9E8TQxv8PpZZq4DYBCkV5qkpFS/";
    address payable public royaltyAddress;
    bool public hasSaleStarted = false;
    uint256 public minitingFees;
    uint256 public maxApesMint;
    uint256 public royalties;
    bool public revealed = false;

    constructor() ERC721("Nostalgic Apes", "NA") {
        royaltyAddress = payable(0x2922df85Ee4fc179986196af3dc5d4708A39ec4e);
        royalties=10;
        maxApesMint=100;
     }

    function setBaseURI(string memory baseURI) public onlyOwner {
        _baseTokenURI = baseURI;
    }
    
     // Start Sale, we can start minting!
    function startSale() public onlyOwner {
        hasSaleStarted = true;
    }

    // Pause Sale
    function pauseSale() public onlyOwner {
        hasSaleStarted = false;
    }

    // Function for set the royalties 
    function setRoyalties(uint256 _newfees) public onlyOwner{
        royalties=_newfees;
    }

    // Function for set the Minting Fees 
    function setMintFees(uint256 _minitingFees)public onlyOwner{
        minitingFees=_minitingFees;
    }

    // Function for set the royalty Address
    function setRoyaltyAddress(address payable _newAddress)public onlyOwner{
        royaltyAddress=_newAddress;
    }
    
    // Function for set the Max Minitng Apes 
    function setMaxMintingApes(uint256 _numberOfAPes) public onlyOwner{
        maxApesMint=_numberOfAPes;
    }
    function _baseURI() internal view virtual override returns (string memory) {
        return _baseTokenURI;
    }

    function getBaseURI() public view returns (string memory) {
        return _baseTokenURI;
    }
    
    function tokenURI(uint256 _tokenId)
        public
        view
        override
        returns (string memory) {
        string  memory json=".json";
        uint256 totalSupply = totalSupply();
        require(_tokenId <= totalSupply, "That token hasn't been minted yet");
        return string(abi.encodePacked(_baseTokenURI, Strings.toString(_tokenId),json));
    }

    function walletOfOwner(address _owner)
    public
    view
    returns (uint256[] memory)
    {
        uint256 ownerTokenCount = balanceOf(_owner);
        uint256[] memory tokenIds = new uint256[](ownerTokenCount);
        for (uint256 i; i < ownerTokenCount; i++) {
            tokenIds[i] = tokenOfOwnerByIndex(_owner, i);
        }
    return tokenIds;
    }
    /*
    *@dev mint Fucntion is to mint the NFTS 
    @dev _count is the number of NFTS you want to Mint 
    */
    function mint(uint256 _count) public payable {  
        require(!isBlacklisted[msg.sender], "caller is backlisted"); 
        uint256 totalSupply = totalSupply();
        require(totalSupply <= MAX_SUPPLY, "Sold out");
        require(hasSaleStarted == true, "Sale hasn't started");
        require(totalSupply + _count <= MAX_SUPPLY, "Not enough tokens left");
        require(_count <= maxApesMint, "Mint maxApesMint or fewer, please.");
        require(msg.value >= _count.mul(minitingFees), "The value submitted with this transaction is too low.");
        payable(owner()).transfer(msg.value);
        
        for (uint256 i=1; i <=_count; i++) {
            _safeMint(msg.sender, totalSupply + i);
        }
    }
    
    /*
    *@dev mintOwner Fucntion is to mint the NFTS for owner
    @dev _count is the number of NFTS you want to Mint 
    */
    function mintOwner(uint256 _count) public onlyOwner {  
       
        uint256 totalSupply = totalSupply();
        require(totalSupply < MAX_SUPPLY, "Sold out");
        require(totalSupply + _count <= MAX_SUPPLY, "Not enough tokens left");
        require(_count <= maxApesMint, "Mint maxApesMint or fewer, please.");
        for (uint256 i; i < _count; i++) {
            _safeMint(msg.sender, totalSupply + i);
        }
    }

    function withdraw() public onlyOwner {
        uint balance = address(this).balance;
        payable(msg.sender).transfer(balance);
    }
}
function startSale() public onlyOwner {
    hasSaleStarted = true;
}

// Start Sale, we can start minting!