contract ChubbyCherubs is ERC721, Ownable {
    uint256 private mintCount = 0;

    uint256 public constant MAX_CHUB = 1111;
    uint256 public price = 70000000000000000; //0.07 Ether
    string baseTokenURI;
    bool public saleOpen;

    event ChubMinted(uint256 totalMinted);

    constructor(string memory baseURI) ERC721("Chubby Cherubs", "CHUB") {
        setBaseURI(baseURI);
    }

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

    function totalSupply() public view returns (uint256) {
        return mintCount;
    }

    function setPrice(uint256 _newPrice) external onlyOwner {
        price = _newPrice;
    }

    //Close sale if open, open sale if closed
    function flipSaleState() external onlyOwner {
        saleOpen = !saleOpen;
    }

    function withdrawAll() external onlyOwner {
        (bool success, ) = msg.sender.call{value: address(this).balance}("");
        require(success, "Transfer failed.");
    }

    function airdrop(address[] calldata _recipients) external onlyOwner {
        uint256 supply = totalSupply();
        require(
            supply + _recipients.length <= MAX_CHUB,
            "Airdrop will exceed maximum supply of CHUB"
        );
        require(_recipients.length != 0, "Address not found");
        mintCount += _recipients.length;
        for (uint256 i = 0; i < _recipients.length; i++) {
            require(_recipients[i] != address(0), "Airdrop to Null address");
            handleMint(_recipients[i], ++supply);
        }
    }

    //mint CHUB
    function mint(uint256 _count) external payable {
        uint256 supply = totalSupply();
        require(supply + _count <= MAX_CHUB, "Exceeds maximum supply of CHUB");
        require(_count > 0, "Minimum 1 CHUB has to be minted per transaction");

        if (msg.sender != owner()) {
            require(saleOpen, "Sale is not open yet");
            require(
                _count <= 10,
                "Maximum 10 Chubby Cherubs can be minted per transaction"
            );
            require(
                msg.value >= price * _count,
                "Ether sent with this transaction is not correct"
            );
        }

        mintCount += _count;

        for (uint256 i = 0; i < _count; i++) {
            handleMint(msg.sender, ++supply);
        }
    }

    function handleMint(address _to, uint256 tokenId) private {
        _safeMint(_to, tokenId);
        emit ChubMinted(tokenId);
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return baseTokenURI;
    }
}
function flipSaleState() external onlyOwner {
    saleOpen = !saleOpen;
}

//Close sale if open, open sale if closed