contract RebelsInDisguise is ERC721, ERC721Enumerable, Ownable {
    constructor(string memory name, string memory symbol) ERC721(name, symbol) 
    {}
    
    address public rebelsCoinAddress;
    string public _baseUri;
    uint256 public _tokenId = 0;
    bool public isMintingLocked = false;

    function mintTransfer(address to, uint256 _count) public {
        require(msg.sender == rebelsCoinAddress, "Not authorized");
        require(isMintingLocked == false, "Minting has been locked!");
        
        for (uint256 index = 0; index < _count; index++) {
            _tokenId ++;
            _mint(to, _tokenId);
        }
    }
    
    // Change the Rebels Coin address contract
    function setRebelsCoinAddress(address newAddress) public onlyOwner { 
        rebelsCoinAddress = newAddress;
    }
    
    function setBaseUri(string memory baseUri) public onlyOwner {
        _baseUri = baseUri;
    }

    // Mint function for only owner to mint other addresses. This will be used for special NFTs rewarded to the community
    function mintToAddress(address contractAddress, uint256 _count) public onlyOwner {
        require(isMintingLocked == false, "Minting has been locked!");

        for (uint256 index = 0; index < _count; index++) {
            _mint(contractAddress, _tokenId);
            _tokenId ++;
        }
    }

    // Lock future mints. There is no way to open minting again
    function lockMinting() public onlyOwner {
        isMintingLocked = true;
    }
    
	function tokensOfOwner(address _owner) external view returns (uint256[] memory) {
		uint256 tokenCount = balanceOf(_owner);
		if (tokenCount == 0) return new uint256[](0);
		else {
			uint256[] memory result = new uint256[](tokenCount);
			uint256 index;
			for (index = 0; index < tokenCount; index++) {
				result[index] = tokenOfOwnerByIndex(_owner, index);
			}
			return result;
		}
	}

    function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {
        return super.supportsInterface(interfaceId);
    }
    function _baseURI() internal view override returns (string memory) {
        return _baseUri;
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }   
}
function setRebelsCoinAddress(address newAddress) public onlyOwner { 
    rebelsCoinAddress = newAddress;
}

// Change the Rebels Coin address contract