contract HappyBirthday is ERC721Enumerable, Ownable {
    uint256 public constant PINATA_SUPPLY = 3660;
    uint256 public constant PINATA_PRICE = 55000000000000000; // 0.055 ETH

    bool _saleIsActive = false;
    string _baseTokenURI;

    /**
     * @dev Initializes the contract by setting a `baseURI` for the token collection.
     */
    constructor(string memory baseURI) ERC721("HappyBirthdayPinatas", "HBD") {
        setBaseURI(baseURI);
    }

    /**
     * @notice Mints `tokenId` and transfers it to `to`. A fee is deposited into the contract.
     *
     * Requirements:
     * - `_saleIsActive` must be set to true by the contract owner
     * - `tokenId` must be in range 0 TO `NORMAL_PINATA_SUPPLY`
     * - Message value must be greater than or equal to static price for the token. The single `SPECIAL_PINATA_TOKEN_ID` requires a higher value.
     * - `tokenId` must not exist
     */
    function mint(address to, uint256 tokenId) public payable {
        if (msg.sender != owner()) {
            require(_saleIsActive, "Sales are not active");
        }

        require(tokenId < PINATA_SUPPLY, "Invalid tokenId");
        require(msg.value >= PINATA_PRICE, "Value below price");

        _safeMint(to, tokenId);
    }

    /**
     * @dev Sets the `baseURI` for the token collection.
     */
    function setBaseURI(string memory baseURI) public onlyOwner {
        _baseTokenURI = baseURI;
    }

    /**
     * @dev Sets minting sales to the `isActive` status
     * @param isActive A boolean that denotes if sales should be set to active.
     */
    function setSaleActive(bool isActive) public onlyOwner {
        _saleIsActive = isActive;
    }

    /**
     * @dev Sends full contract balance to the message sender
     */
    function withdraw() public payable onlyOwner {
        uint balance = address(this).balance;
        payable(msg.sender).transfer(balance);
    }

    /**
     * @dev Base URI for computing {tokenURI}
     */
    function _baseURI() internal view virtual override returns (string memory) {
        return _baseTokenURI;
    }

    /**
     * @dev Overriding function to prevent ability to renounce ownership
     */
    function renounceOwnership() public virtual override onlyOwner {
        revert("Cannot renounce ownership");
    }
}
/**
 * @title HappyBirthday NFT minting contract
 * @dev Extends ERC721 Non-Fungible Token Standard basic implementation
 */
function _baseURI() internal view virtual override returns (string memory) {
    return _baseTokenURI;
}

/**
 * @dev Base URI for computing {tokenURI}
 */