contract pixelGans is ERC721Enumerable, Ownable{
    using SafeMath for uint256;
    using Address for address;
    using Strings for uint256;
    using Counters for Counters.Counter;
    
    
    Counters.Counter private _tokenIdCounter;

    uint256 public NFT_PRICE = 250000000000000000; // 0.25 ETH
    uint256 public MAX_SUPPLY = 100;
    bool public saleIsActive = false;

    string private _baseURIExtended;
    mapping (uint256 => string) _tokenURIs;
    
    
    
    //For Claiming NFT Royalties
    // Mapping from token ID to the amount of claimable eth in gwei
    mapping(uint256 => uint256) private _claimableEth;
    
    event PaymentReleased(address to, uint256 amount);

    event EthDeposited(uint256 amount);

    event EthClaimed(address to, uint256 amount);
    
    

    constructor() ERC721("PixelGans", "PXLGANS0x"){
    }


    function flipSaleState() public onlyOwner {
        saleIsActive = !saleIsActive;
    }

    function withdraw() public onlyOwner {
        uint balance = address(this).balance;
        payable(msg.sender).transfer(balance);
        
        for(uint256 i = 0; i < totalSupply(); i++) {
            // Empty out all the claimed amount so as to protect against re-entrancy attacks.
            _claimableEth[i] = 0;
        }
        
    }

    function setMaxTokenSupply(uint256 maxSupply) public onlyOwner {
        MAX_SUPPLY = maxSupply;
    }

    function mint() public payable {
        require(saleIsActive, "Sale is not active at the moment");
        require((totalSupply() + 1) <= MAX_SUPPLY, "Purchase would exceed max supply");
        require(NFT_PRICE == msg.value, "Sent ether value is incorrect, mint cost is 0.25 ether");
        
        if ((totalSupply() + 1) <= MAX_SUPPLY) {
            _safeMint(msg.sender, totalSupply());
            _tokenIdCounter.increment();
        }
        
    }
   
    /*
    * Deposit eth for distribution to token owners.
    */
    function deposit() public payable  {
        uint256 tokenCount = totalSupply();
        uint256 claimableAmountPerToken = msg.value / tokenCount;

        for(uint256 i = 0; i < tokenCount; i++) {
            // Iterate over all existing tokens (that have not been burnt)
            _claimableEth[tokenByIndex(i)] += claimableAmountPerToken;
        }

        emit EthDeposited(msg.value);
    }

    /*
    * Get the claimable balance of a token ID.
    */
    function claimableBalanceOfTokenId(uint256 tokenId) public view returns (uint256) {
        return _claimableEth[tokenId];
    }
    
    /*
    * Get the total claimable balance for an owner.
    */
    function claimableBalance(address owner) public view returns (uint256) {
        uint256 balance = 0;
        uint256 numTokens = balanceOf(owner);

        for(uint256 i = 0; i < numTokens; i++) {
            balance += claimableBalanceOfTokenId(tokenOfOwnerByIndex(owner, i));
        }

        return balance;
    }

    function claim() public {
        uint256 amount = 0;
        uint256 numTokens = balanceOf(msg.sender);

        for(uint256 i = 0; i < numTokens; i++) {
            uint256 tokenId = tokenOfOwnerByIndex(msg.sender, i);
            amount += _claimableEth[tokenId];
            // Empty out all the claimed amount so as to protect against re-entrancy attacks.
            _claimableEth[tokenId] = 0;
        }

        require(amount > 0, "There is no amount left to claim");

        emit EthClaimed(msg.sender, amount);

        // We must transfer at the very end to protect against re-entrancy.
        Address.sendValue(payable(msg.sender), amount);
    }


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

    // Sets base URI for all tokens, only able to be called by contract owner
    function setBaseURI(string memory baseURI_) external onlyOwner {
        _baseURIExtended = baseURI_;
    }
    
       
    function setCost(uint256 _amount) external onlyOwner {
        NFT_PRICE = _amount;
    }
    
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory _tokenURI = _tokenURIs[tokenId];
        string memory base = _baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(base, _tokenURI));
        }
        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
        return string(abi.encodePacked(base, tokenId.toString()));
    }
}
function claimableBalanceOfTokenId(uint256 tokenId) public view returns (uint256) {
    return _claimableEth[tokenId];
}

/*
 * Get the claimable balance of a token ID.
 */