contract PunkCow is ERC721Enumerable, Ownable {
    
    string _varBaseURI;
    
    uint256 private price = 0.025 ether;
    uint256 private reserved = 500;
    bool public burningEnabled = false;
    bool public mintingEnabled = false;

    constructor(string memory baseURI) ERC721("Punk Cow", "PunkCow") {
        setBaseURI(baseURI);
        _safeMint( 0xcd05516D2a4fA550Fef59ab32e7DCc9269B24c3D, 0);
        _safeMint( 0x0B708A7DF05BA597D0F8FB703FaCB4aC6f316293, 1);
    }

    function mint(uint256 _quantity) public payable {
        uint256 supply = totalSupply();

        require(mintingEnabled, "minting is not enabled yet");
        require(_quantity <= 25, "You can mint at most 25 at a time");
        require(msg.value == getPrice(_quantity), "Ether amount is not correct");
        require(supply < 10000 - reserved, "Sorry, we sold out PunkCows");
        require(supply + _quantity <= 10000 - reserved, "Sorry, you exceed our max supply");
        
        for (uint i = 0; i < _quantity; i++) {
            uint256 newTokenId = supply + i;
            _safeMint(msg.sender, newTokenId);
        }
    }

    function giveAway(address _to, uint256 _quantity) external onlyOwner() {
        require( _quantity <= reserved, "Exceeds reserved PunkCow supply" );

        uint256 supply = totalSupply();
        for(uint256 i; i < _quantity; i++){
            uint256 newTokenId = supply + i;
            _safeMint( _to, newTokenId);
        }
        reserved -= _quantity;
    }

    function setReserved(uint256 _newReserved) public onlyOwner {
        require(_newReserved <= remainingSupply(), "Exceed remaining supply");
        reserved = _newReserved;
    }

    function getReserved() public view onlyOwner returns(uint256) {
        return reserved;
    }

    // Adjust Eth volatility
    function setPrice(uint256 _newPrice) public onlyOwner {
        price = _newPrice;
    }

    function getPrice(uint256 _quantity) public view returns(uint256) {
        return price * _quantity;
    }
    
    function withdraw() public onlyOwner {
        payable(msg.sender).transfer(address(this).balance);
    }

    function toggleBurningEnabled() public onlyOwner {
        burningEnabled = !burningEnabled;
    }

    function toggleMintingEnabled() public onlyOwner {
        mintingEnabled = !mintingEnabled;
    }

    function burn(uint256 tokenId) public virtual {
        require(burningEnabled, "burning is not yet enabled");
        require(_isApprovedOrOwner(_msgSender(), tokenId), "You are not the owner nor approved of this Punk Cow");
        _burn(tokenId);
    }

    function remainingSupply() public view returns(uint256) {
        return 10000 - totalSupply();
    }

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

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

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

// Adjust Eth volatility