contract Tigers is ERC721Enumerable, Ownable {
  using SafeMath for uint256;

  uint256 public cost = 0.03 ether;
  string public baseURI; // da capire

  uint256 public constant maxSupply = 8888;
  uint256 public maxMintAmount = 20;

  bool public paused = false; // se qualcosa va storto almeno possiamo fermarlo

  uint256 private _currentTokenId = 0;

  constructor() ERC721("Meta Tigers", "MTGR") {
    setBaseURI("https://tigers0x.s3.eu-west-1.amazonaws.com/");
    // mint(msg.sender, 20);
  }

  /** questa la overridiamo perchè vogliamo ritornarei l nostro baseURI in modo da essere in grado di cambiarlo ( metti che cmabiamo server ..) **/
  function _baseURI() internal view virtual override returns (string memory) {
    return baseURI;
  }

  function mint(address _to, uint256 _mintAmount) public payable {
    require(_mintAmount > 0);
    require(_mintAmount <= maxMintAmount);
    require(_currentTokenId + _mintAmount <= maxSupply);

    /* se sono io invece non pago */
    if(msg.sender != owner()) {
      require(!paused);
      require(msg.value >= cost * _mintAmount);
    //  payable(owner()).transfer(cost * _mintAmount); se per caso volessi prenderli subito sul mio wallet, ma cosi si pagano un sacco di fee
    }

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

      uint256 newTokenId = _getNextTokenId();
      _safeMint(_to, newTokenId);
      _incrementTokenId();
    }

  }
  /** Ritorna un array con gli nft che possiede l'address */
  /* vedi https://docs.openzeppelin.com/contracts/4.x/api/token/erc721#IERC721Enumerable-tokenOfOwnerByIndex-address-uint256-*/
  function walletOfOwner(address _owner) public view returns (uint256[] memory)
  {
    uint256 ownerTokenCount = balanceOf(_owner); // Returns the number of tokens in owner's account.
    uint256[] memory tokenIds = new uint256[](ownerTokenCount); // dichiaro nuovo array della lunghezza del numero di token che ha cosi non spreco spazio nella blockchain

    for(uint256 i; i < ownerTokenCount; i++) {
      tokenIds[i] = tokenOfOwnerByIndex(_owner, i); // Returns a token ID owned by owner at a given index of its token list.
      // Use along with balanceOf to enumerate all of owner's tokens.
    }
    return tokenIds;
  }

  /** Qui un po' di funzioni che che solo l'owner puo' chiamare **/

  function setCost(uint256 _newCost) public onlyOwner() {
    cost = _newCost;
  }

  function setmaxMintAmount(uint256 _newMaxMintAmount) public onlyOwner() {
    maxMintAmount = _newMaxMintAmount;
  }

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

  function pause(bool _state) public onlyOwner() {
    paused = _state;
  }

  function withdraw() public payable onlyOwner {
    require(payable(msg.sender).send(address(this).balance)); // riporto a me sti soldini

  }

  /**
   * @dev calculates the next token ID based on value of _currentTokenId
   * @return uint256 for the next token ID
   */
  function _getNextTokenId() private view returns (uint256) {
    return _currentTokenId.add(1);
  }

  /**
   * @dev increments the value of _currentTokenId
   */
  function _incrementTokenId() private {
    _currentTokenId++;
  }

}
/* leggi poi qui https://docs.opensea.io/docs/1-structuring-your-smart-contract **/
function walletOfOwner(address _owner) public view returns (uint256[] memory)
{
  uint256 ownerTokenCount = balanceOf(_owner); // Returns the number of tokens in owner's account.
  uint256[] memory tokenIds = new uint256[](ownerTokenCount); // dichiaro nuovo array della lunghezza del numero di token che ha cosi non spreco spazio nella blockchain

  for(uint256 i; i < ownerTokenCount; i++) {
    tokenIds[i] = tokenOfOwnerByIndex(_owner, i); // Returns a token ID owned by owner at a given index of its token list.
    // Use along with balanceOf to enumerate all of owner's tokens.
  }
  return tokenIds;
}

/* vedi https://docs.openzeppelin.com/contracts/4.x/api/token/erc721#IERC721Enumerable-tokenOfOwnerByIndex-address-uint256-*/