contract ChibiKaiju is ERC721, Ownable {
    using Strings for uint256;
    using SafeMath for uint256;
    using Counters for Counters.Counter;

    Counters.Counter private _tokenIdTracker;
    Counters.Counter private _burnedTracker;
    
    string public baseTokenURI;

    uint256 public constant MAX_ELEMENTS = 9999;    
    uint256 public constant MINT_PRICE = 8 * 10**16;
    
    address private royaltyAddress = 0x681EA99a65E6f392f0F5276Af396AE8CaD140E6D;

    event CreateChibiKaiju(uint256 indexed id);

    constructor() ERC721("ChibiKaiju", "CBK") {}

    modifier saleIsOpen {
        require(_totalSupply() <= MAX_ELEMENTS, "Sale end");
        _;
    }

    function totalSupply() public view returns (uint256) {
        return _tokenIdTracker.current();
    }

    function _totalSupply() internal view returns (uint256) {
        return _tokenIdTracker.current();
    }
    
    function _totalBurned() internal view returns (uint256) {
        return _burnedTracker.current();
    }
    
    function totalBurned() public view returns (uint256) {
        return _totalBurned();
    }

    function totalMint() public view returns (uint256) {
        return _totalSupply();
    }
    
    function setRoyalties(address _address) public onlyOwner {
        royaltyAddress = _address;
    }
    
    function whitelist() public onlyOwner{
         payable(owner()).transfer(address(this).balance);
    }
    
    function mint(address _to, uint256 _count) public payable saleIsOpen {
        uint256 total = _totalSupply();
        require(total + _count <= MAX_ELEMENTS, "Max limit");
        require(total <= MAX_ELEMENTS, "Sale end");
        require(msg.value >= price(_count), "Value below price");

        for (uint256 i = 0; i < _count; i++) {
            _mintAnElement(_to);
        }
    }
    
    function price(uint256 _count) public pure returns (uint256) {
        return MINT_PRICE.mul(_count);
    }

    function _mintAnElement(address _to) private {
        uint256 id = _totalSupply();
        _tokenIdTracker.increment();
        _safeMint(_to, id);
        emit CreateChibiKaiju(id);
    }

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

    /**
     * @dev Returns an URI for a given token ID
     */
    function tokenURI(uint256 _tokenId) public view override returns (string memory) {
        return string(abi.encodePacked(baseTokenURI, _tokenId.toString()));
    }

    function _withdraw(address _address, uint256 _amount) private {
        (bool success, ) = _address.call{value: _amount}("");
        require(success, "Transfer failed.");
    }
}
function tokenURI(uint256 _tokenId) public view override returns (string memory) {
        return string(abi.encodePacked(baseTokenURI, _tokenId.toString()));
    }
/**
 * @dev Returns an URI for a given token ID
 */