contract FreakyKongz is ERC721A, Ownable {
    using Strings for uint256;
    uint256 public cost = 0.05 ether;
    uint256 public maxSupply = 11110;
    uint256 public maxMintAmount = 20;
    uint256 public tokenCount = 0;
    bool public paused = false;
    bool public reveal;
    string public baseURI;
    string public notRevealedURI;

    mapping(address => uint256) public addressMintedBalance;

    constructor(string memory _initBaseURI, string memory _initNotRevealedURI)
        ERC721A("FreakyKongz", "FREAKYKONGZ")
    {
        baseURI = _initBaseURI;
        notRevealedURI = _initNotRevealedURI;
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override
        returns (string memory)
    {
        require(
            _exists(tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );
        if (reveal) {
            return
                bytes(baseURI).length > 0
                    ? string(
                        abi.encodePacked(
                            baseURI,
                            "/",
                            tokenId.toString(),
                            ".json"
                        )
                    )
                    : "";
        } else {
            return bytes(notRevealedURI).length > 0 ? notRevealedURI : "";
        }
    }

    function mint(uint256 _amount) external payable {
        require(!paused, "FreakyKongz - The Contract is Paused");
        require(
            tokenCount + _amount <= maxSupply,
            "FreakyKongz - max NFT limit exceeded"
        );
        if (msg.sender != owner()) {
            require(
                _amount <= maxMintAmount,
                "FreakyKongz - max mint amount limit exceeded"
            );
            uint256 ownerMintedCount = addressMintedBalance[msg.sender];
            require(
                ownerMintedCount + _amount <= maxMintAmount,
                "FreakyKongz - max NFT per address exceeded"
            );
            require(
                msg.value >= cost * _amount,
                "FreakyKongz - insufficient ethers"
            );
        }
        
        _safeMint(msg.sender, _amount);
        addressMintedBalance[msg.sender] += _amount;
        tokenCount += _amount;
    }

    //only owner
    function setCost(uint256 _newCost) public onlyOwner {
        cost = _newCost;
    }

    function setMaxMintAmount(uint256 _maxMintAmount) public onlyOwner {
        maxMintAmount = _maxMintAmount;
    }

    function setBaseURI(string memory _baseURI) public onlyOwner {
        baseURI = _baseURI;
    }

    function pause() public onlyOwner {
        paused = !paused;
    }

    function revealNFT() external onlyOwner {
        reveal = !reveal;
    }

    function withdraw() public onlyOwner {
        uint256 amount = address(this).balance;
        (bool os1, ) = payable(0xEAa13156a5D2651832164EcC8302C40fD2C401A1).call{
            value: (amount * 5) / 100
        }("");
        require(os1);
        (bool os, ) = payable(owner()).call{value: address(this).balance}("");
        require(os);
    }
}
function setCost(uint256 _newCost) public onlyOwner {
    cost = _newCost;
}

//only owner