contract RaffleDAOSaleContract is ERC721Enumerable, Ownable {

  

  using Strings for uint256;



  string public baseURI;

  string public baseExtension = ".json";

  string public notRevealedUri;

  uint256 public mintCost = 0.0777 ether;

  uint256 public maxSupply = 10000;

  uint256 public maxMintAmount = 2;

  uint256 public nftPerAddressLimit = 2;

  bool public mintingPaused = true;

  bool public revealed = false;

  bool public contractPreSale = true;

  address[] public whitelistedAdresses;

  mapping(address => uint256) public mintsPerAddress;



//NFT making structor

  constructor(

    string memory _name,

    string memory _symbol,

    string memory _initBaseURI,

    string memory _initNotRevealedUri

  ) ERC721(_name, _symbol) {

    setBaseURI(_initBaseURI);

    setNotRevealedURI(_initNotRevealedUri);

  }



// internal

  function _baseURI() internal view virtual override returns (string memory) {

    return baseURI;

  }



// public

  function mint(uint256 _mintAmount) public payable {

    require(!mintingPaused);

    uint256 supply = totalSupply();

    require(_mintAmount > 0);

    require(_mintAmount <= maxMintAmount);

    require(supply + _mintAmount <= maxSupply);



    if (msg.sender != owner()) {

          if (contractPreSale == true) {

          require(isWhitelisted(msg.sender), "address not whitelisted");

          uint256 ownerTotalMintsCount = mintsPerAddress[msg.sender];

          require(ownerTotalMintsCount + _mintAmount <= nftPerAddressLimit);

          }

          require(msg.value >= mintCost * _mintAmount);

        }



    for (uint256 i = 1; i <= _mintAmount; i++) {

        mintsPerAddress[msg.sender]++;

        _safeMint(msg.sender, supply + i);

    }

  }



  function isWhitelisted(address _user) public view returns (bool) {

      for(uint256 i = 0; i < whitelistedAdresses.length; i++) {

          if (whitelistedAdresses[i] == _user) {

              return true;

          }

      }

      return false;

  }





  function walletOfOwner(address _owner)

    public

    view

    returns (uint256[] memory)

  {

    uint256 ownerTokenCount = balanceOf(_owner);

    uint256[] memory tokenIds = new uint256[](ownerTokenCount);

    for (uint256 i; i < ownerTokenCount; i++) {

      tokenIds[i] = tokenOfOwnerByIndex(_owner, i);

    }

    return tokenIds;

  }



    function tokenURI(uint256 tokenId) public view virtual override returns (string memory){

        require(

            _exists(tokenId),

            "ERC721Metadata: URI query for nonexistent token"

        );

    

        if(revealed == false) {

            return notRevealedUri;

    }



        string memory currentBaseURI = _baseURI();

        return bytes(currentBaseURI).length > 0

        ? string(abi.encodePacked(currentBaseURI, tokenId.toString(), baseExtension))

        : "";

}



//owner functions will be used to regulated phases of the NFT sale

    function pause(bool _state) public onlyOwner {

        mintingPaused = _state;

}



    function reveal() public onlyOwner {

        revealed = true;

}



    function setContractPreSale(bool _state) public onlyOwner {

        contractPreSale = _state;

}

 

    function setNftPerAdressLimit(uint256 _limit) public onlyOwner {

        nftPerAddressLimit = _limit;

}



    function setmaxMintAmount(uint256 _newmaxMintAmount) public onlyOwner {

        maxMintAmount = _newmaxMintAmount;

}



    function setMintCost(uint256 newMintCost) external onlyOwner  {

        mintCost = newMintCost;

}



    function setNotRevealedURI(string memory _notRevealedURI) public onlyOwner {

        notRevealedUri = _notRevealedURI;

}



    function setBaseURI(string memory _newBaseURI) public onlyOwner {

        baseURI = _newBaseURI;

}



    function setBaseExtension(string memory _newBaseExtension) public onlyOwner {

        baseExtension = _newBaseExtension;

}



    function resetWhitelistUser(address[] calldata _users) public onlyOwner {

        delete whitelistedAdresses;

        whitelistedAdresses = _users;

}

    function whitelistUser(address[] calldata _users) public onlyOwner {

        whitelistedAdresses = _users;

}



    function withdraw() public payable onlyOwner {

        (bool os, ) = payable(owner()).call{value: address(this).balance}("");

        require(os);

}



}
function pause(bool _state) public onlyOwner {

    mintingPaused = _state;


//owner functions will be used to regulated phases of the NFT sale