contract BitShiftModJourneys is
  ERC721,
  ERC721Enumerable,
  ERC721Burnable,
  Ownable
{
  using Strings for uint256;
  
  uint256 private constant MAX_SUPPLY = 256;
  uint256 private constant RESERVE_SUPPLY = 16;  
  uint256 private constant PRICE_PER_TOKEN = 50000000000000000; 
  
  string private _baseURIextended = "https://bitshiftmod.com/projects/journeys/metadata/";

  constructor() ERC721("bitshiftmod", "JOURNEYS") {}

  function reserve() public onlyOwner {
    uint supply = totalSupply();
    uint i;
    for (i = 0; i < RESERVE_SUPPLY; i++) {
        _safeMint(msg.sender, supply + i);
    }
  }

  function mint() public payable {
      uint256 ts = totalSupply();
        
      require(ts < MAX_SUPPLY, "Purchase would exceed max tokens");
      require(PRICE_PER_TOKEN <= msg.value, "Ether value sent is not correct");
      
      _safeMint(msg.sender, ts);
  }
  
  function withdraw() public onlyOwner {
      uint balance = address(this).balance;
      payable(msg.sender).transfer(balance);
  }

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

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

  function tokenURI(uint256 tokenId)
    public
    view
    virtual
    override(ERC721)
    returns (string memory)
  {
    require(
      _exists(tokenId),
      "ERC721Metadata: URI query for nonexistent token"
    );

    // Concatenate the tokenID to the baseURI.
    return string(abi.encodePacked(_baseURIextended, tokenId.toString()));
  }

  // 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.