contract LuckyBananaApes is Context, ERC721Enumerable, ERC721Burnable, Ownable {
    uint internal constant MAX_MINTS_PER_TRANSACTION = 20;
    uint internal constant TOKEN_LIMIT = 10000;
    
    uint256 internal _mintPrice = 0;
    
    address payable internal devTeam = payable(0x273271b8FBCC295a48B7C4A3E65073591ACc2CA0);
    string internal _baseTokenURI;
    bool internal saleStarted = false;
    bool internal URISet = false;
    uint internal devSupplyAwarded = 0;

    uint internal nextTokenId = 1;

    /**
     * Token URIs will be autogenerated based on `baseURI` and their token IDs.
     * See {ERC721-tokenURI}.
     */
    constructor(string memory name, string memory symbol,string memory baseTokenURI) ERC721(name, symbol) {
         _baseTokenURI = baseTokenURI;
        //dont call awardDevs() here, initial supply here, too much gas for one transaction
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return _baseTokenURI;
    }   
    
    /**
    * Can only be called twice. Gives 20 total tickets to devs for giveaways, marketing purposes and team members.
    */
    function give10TicketsToDevs() external onlyOwner {
        require(saleStarted == false,"Sale has already started");
        require(devSupplyAwarded < 3,"Dev supply has already been awarded");
        uint i;
        uint id;

        for(i = 0; i < 10; i++){
            id = nextTokenId++;
            _mint(devTeam, id);
        }

        devSupplyAwarded = devSupplyAwarded+1;
    } 

    
    /**
     * @dev Creates a new token. Its token ID will be automatically
     * assigned (and available on the emitted {IERC721-Transfer} event), and the token
     * URI autogenerated based on the base URI passed at construction.
     *
     * See {ERC721-_mint}.
     * 
     */
    function mint(address to, uint amount) external payable{
        //check sale start
        require(saleStarted == true, "Sale has not started yet");

        //only 8192 birbs
        require(nextTokenId <= TOKEN_LIMIT, "No Tickets left");

        //mint at least one
        require(amount > 0, "Must mint at least one");

        //32 max per transaction
        require(amount <= MAX_MINTS_PER_TRANSACTION, "Trying to mint too many");

        //dont overmint
        require(amount <= TOKEN_LIMIT+1-nextTokenId,"Not enough Tickets left to mint");

        //check payment
        require(msg.value >= _mintPrice * amount, "msg.value too low");

        uint id;
        uint i;

        for(i = 0; i < amount; i++){
            id = nextTokenId++;
            _mint(to, id);
        }

    }

    /**
     * @dev Withdraws funds to dev 
     *
     */
    function withdrawAll() public payable onlyOwner {
    require(payable(msg.sender).send(address(this).balance));
  }

    /**
    * Devs cant change URI after the sale begins 
    */
    function setBaseURI(string memory baseTokenURI) external onlyOwner {
        require(saleStarted == false,"Can't change metadata after the sale has started");
        _baseTokenURI = baseTokenURI;
        URISet = true;
    }

    /**
    * Start the sale (cant be stopped later)
    */
    function startSale(uint256 mintPrice) external virtual onlyOwner {
        require(saleStarted == false,"Sale has already started");
        require(URISet == true, "URI not set");
        require(mintPrice > 0.01 ether,"Price too low");
        _mintPrice = mintPrice;
        saleStarted = true;
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC721Enumerable) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    function getAmountMinted() external view returns (uint256) {
        return nextTokenId;
    }

    function getMaxSupply() external pure returns (uint256) {
        return TOKEN_LIMIT;
    }

    function getMintPrice() external view returns (uint256) {
        return _mintPrice;
    }

    function hasSaleStarted() external view returns (bool) {
        return saleStarted;
    }

}
function give10TicketsToDevs() external onlyOwner {
    require(saleStarted == false,"Sale has already started");
    require(devSupplyAwarded < 3,"Dev supply has already been awarded");
    uint i;
    uint id;

    for(i = 0; i < 10; i++){
        id = nextTokenId++;
        _mint(devTeam, id);
    }

    devSupplyAwarded = devSupplyAwarded+1;
} 

/**
 * Can only be called twice. Gives 20 total tickets to devs for giveaways, marketing purposes and team members.
 */