contract DoggyDao is ERC721, ERC721Enumerable, Ownable {

    bool public _isSaleActive = true;
    bool public _isFreeMint = true;
    uint256 constant public MAX_SUPPLY = 888;  
    uint256 public mintPrice = 0.025 ether;
    uint256 public maxMint = 5;

    string private _baseURIExtended = "ipfs://QmXJ4Mg5fQvuZweneiUTPzSDMm4zjQ81QhSWz4Re6WeHr7/";

    event TokenMinted(uint256 supply);

    constructor() ERC721("DoggyDao", "DDao") {}

    function filpSaleActive() public onlyOwner {
        _isSaleActive = !_isSaleActive;
    }

    function filpFreeMint() public onlyOwner {
        _isFreeMint = !_isFreeMint;
    }

    function setMintPrice(uint256 _mintPrice) public onlyOwner {
        mintPrice = _mintPrice;
    }

    function setBaseURI(string memory baseURI_) external onlyOwner {
        _baseURIExtended = baseURI_;
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return _baseURIExtended;
    }

    function freeMint(uint numOfDoggy) public {
        require(_isSaleActive, 'Sale must be active to mint DoggyDao');
        require(_isFreeMint, 'Free mint close');
        require(totalSupply() + numOfDoggy <= MAX_SUPPLY, 'Sale would exceed max supply');
        require(numOfDoggy <= maxMint, 'Sale would exceed max mint');
        _mint(numOfDoggy, msg.sender);
        emit TokenMinted(totalSupply());
    }

    function mint(uint numOfDoggy) public payable {
        require(_isSaleActive, 'Sale must be active to mint DoggyDao');
        require(numOfDoggy * mintPrice <= msg.value, 'Not enough ether sent');
        require(totalSupply() + numOfDoggy <= MAX_SUPPLY, 'Sale would exceed max supply');
        require(numOfDoggy <= maxMint, 'Sale would exceed max mint');
        _mint(numOfDoggy, msg.sender);
        emit TokenMinted(totalSupply());
    }

    function _mint(uint256 num, address to) internal {
        uint256 supply = totalSupply();
        for (uint256 i = 0; i < num; i++) {
            _safeMint(to, supply + i);
        }
    }

    // Withdraw contract balance in case someone sends Ether to the address.
    function withdraw(address to) public onlyOwner {
        uint256 balance = address(this).balance;
        payable(to).transfer(balance);
    }

    // The following functions are overrides required by Solidity.
    function _beforeTokenTransfer(address from, address to, uint256 tokenId)
        internal
        override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721Enumerable)
        returns (bool) {
        return super.supportsInterface(interfaceId);
    }
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
    internal
    override(ERC721, ERC721Enumerable) {
    super._beforeTokenTransfer(from, to, tokenId);
}

// The following functions are overrides required by Solidity.