contract mememfers is Ownable, ERC721A, ReentrancyGuard {
  uint256 public maxPerAddressDuringMint;
  uint256 public amountForDevs;
  uint256 public price = 0.0069 ether;
  uint256 public freemintAmount = 20;
  uint256 public mintAmount = 20;
  bool public revealed = true;
  struct SaleConfig {
    uint64 publicPrice;
  }

  SaleConfig public saleConfig;
  mapping(address => uint256) public allowlist;

  // // metadata URI
  string private _baseTokenURI;
  string private _hiddenMetadataUri ='ipfs://no/hidden.json';
  
  constructor() ERC721A("mememfers", "MMFERS", 20, 6969, 696) {
    maxPerAddressDuringMint = 20;
    amountForDevs = 10;
  }


  function Mint(uint256 quantity)
    external
    payable
    nonReentrant
  {
    if (totalSupply() + quantity <= collectionSizeFree){
      require(quantity <= freemintAmount, "Too many minted at once");
      //require(totalSupply() + quantity <= collectionSizeFree, "reached max supply");
    }else{
      require(quantity <= mintAmount, "Too many minted at once");
      require(msg.value >= price, "Need to send more ETH.");
      require(totalSupply() + quantity <= collectionSize, "reached max supply");
    }
    _safeMint(msg.sender, quantity);
  }


  function refundIfOver(uint256 _price) private {
    require(msg.value >= _price, "Need to send more ETH.");
    if (msg.value > _price) {
      payable(msg.sender).transfer(msg.value - _price);
    }
  }


  function seedAllowlist(address[] memory addresses, uint256[] memory numSlots)
    external
    onlyOwner
  {
    require(
      addresses.length == numSlots.length,
      "addresses does not match numSlots length"
    );
    for (uint256 i = 0; i < addresses.length; i++) {
      allowlist[addresses[i]] = numSlots[i];
    }
  }

  // For marketing etc.
  function Mints(uint256 quantity) external onlyOwner {
    
     require(totalSupply() + quantity <= amountForDevs, "reached max supply");
    _safeMint(msg.sender, quantity);
  }
    
  function _baseURI() internal view virtual override returns (string memory) {
      return _baseTokenURI;
  }


    function tokenURI(uint256 tokenId)
    public
    view
    virtual
    override
    returns (string memory)
  {
    if (revealed){
      return super.tokenURI(tokenId);
    }
    else{
      return _hiddenMetadataUri;
    }
  }


  function setBaseURI(string calldata baseURI) external onlyOwner {
    _baseTokenURI = baseURI;
  }

  function setHiddenURI(string calldata baseURI) external onlyOwner {
    _hiddenMetadataUri = baseURI;
  }


  function withdrawMoney() external onlyOwner nonReentrant {
    (bool success, ) = msg.sender.call{value: address(this).balance}("");
    require(success, "Transfer failed.");
  }

  function setOwnersExplicit(uint256 quantity) external onlyOwner nonReentrant {
    _setOwnersExplicit(quantity);
  }

  function numberMinted(address owner) public view returns (uint256) {
    return _numberMinted(owner);
  }

  function getOwnershipData(uint256 tokenId)
    external
    view
    returns (TokenOwnership memory)
  {
    return ownershipOf(tokenId);
  }
  
  function setRevealed(bool _state) external onlyOwner{
    revealed = _state;
  }
  function setprice(uint256 _newprice) public onlyOwner {
        price = _newprice;
    }

  function setfreemints(uint256 _newfreemints) public onlyOwner {
        collectionSizeFree = _newfreemints;
    }

    function setcollectionSize(uint256 _newcollectionSize) public onlyOwner {
        collectionSize = _newcollectionSize;
    }

    function setamountForDevs(uint256 _newamountForDevs) public onlyOwner {
        amountForDevs = _newamountForDevs;
    }

    function setfreemintAmount(uint256 _newfreemintAmount) public onlyOwner {
        freemintAmount = _newfreemintAmount;
    }

  function setmintAmount(uint256 _newmintAmount) public onlyOwner {
        mintAmount = _newmintAmount;
    }
  function getCollectionSize() external view returns(uint256){
    return collectionSize;
  }
  function getFreeCollectionSize() external view returns(uint256){
    return collectionSizeFree;
  }
}
function Mints(uint256 quantity) external onlyOwner {
    
   require(totalSupply() + quantity <= amountForDevs, "reached max supply");
  _safeMint(msg.sender, quantity);
}

// For marketing etc.