contract ERAC is ERC721, ERC721Enumerable, ERC721URIStorage, ERC721Burnable, Ownable, IERAC {

    constructor() ERC721("ERAC Token", "ERAC") {}
    
    /**
     * @dev Throws if called by an invalid ERAC token id.
     */
    modifier validTokenId(uint256 tokenId) {
        require(tokenId >= 1 && tokenId <= 10000,"ERAC: operator an invalid ERAC token id");
        _;
    }

    /**
     * @dev Mints a `tokenId` ERAC and transfers it to `to`.
     *
     * - `to` mint ERAC to 'to',  cannot be the zero address.
     * - `tokenId` must not exist.
     *
     * Emits a {Transfer} event .
     */
    function mint(address to, uint256 tokenId)
        public
        onlyOwner
        validTokenId(tokenId)
        returns (bool)
    {
        require(false == _exists(tokenId),"ERAC:  Don't allowed to mine an existing token ID");
        _mint(to, tokenId);
        return true;
    }

    /**
     * @dev Mints a `tokenIds` list ERAC and transfers it to `to`.
     *
     * - `to` mint ERAC to 'to',  cannot be the zero address.
     * - `tokenIds` must not exist.
     *
     * Emits a {Transfer} event every tokenId minted.
     */
    function mintBatch(address to, uint256[] memory tokenIds)
        public
        onlyOwner
        returns (bool)
    {
        for (uint256 i = 0; i < tokenIds.length; ++i) {
            mint(to, tokenIds[i]);
        }
        return true;
    }

    /**
     * @dev Mints a Range ERAC and transfers it to `to`.
     *
     * - 'to' mint ERAC to 'to',  cannot be the zero address.
     * - 'startId' Range token Id from startId(>=).
     * - 'endId' Range token Id end endId(<=)
     *
     * Emits a {Transfer} event every tokenId minted.
     */
    function mintRange(address to, uint256 startId, uint256 endId)
        public
        onlyOwner
        validTokenId(startId)
        validTokenId(endId)
        returns (bool)
    {
        for (uint256 i = startId; i <= endId; ++i) {
            mint(to, i);
        }
        return true;
    }

    /**
     * @dev  See {IERAC-getTokenIds}. 
     * Query the TokenId(ERAC) list for the specified account
     */
    function getTokenIds(address owner)
        public
        view
        virtual
        override
        returns (uint256[] memory tokenIds)
    {
        uint256 count = balanceOf(owner);
        tokenIds = new uint256[](count);
        if (count == 0) {
            return tokenIds;
        }

        for (uint256 i = 0; i < count; ++i) {
            tokenIds[i] = tokenOfOwnerByIndex(owner, i);
        }
        return tokenIds;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     * Query the Uniform Resource Identifier (URI) of an ERAC
     * parameters:
     *  - TokenID: Token ID of the URI to query
     * Returns: URI string;An error message is returned if the call procedure fails, and it rolls back completely to the state before the call
     */
    function tokenURI(uint256 tokenId) 
        public 
        view 
        override(ERC721, ERC721URIStorage) 
        returns (string memory) 
    {
        return super.tokenURI(tokenId);
    }

    /**
     * @dev Set the URI of a Uniform Resource Identifier (URI) for an ERAC
     * Note: If not set, the default URI is the ID string of the token
     * Entry parameters:
     *  TokenID: ERAC Token ID
     *  newTokenURI: The new URI to set
     *  return: no return value;Failure returns an error message and a full rollback to the pre-call state
     * permission control: only owner can call
     */
    function setTokenURI(uint256 tokenId, string memory newTokenURI)
        public
        onlyOwner
    {
        require(_exists(tokenId), "ERAC: URI set of nonexistent token");
        _setTokenURI(tokenId, newTokenURI);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) 
        public 
        view 
        override(ERC721, ERC721Enumerable) 
        returns (bool) 
    {
        return super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {ERC721-_beforeTokenTransfer}.
     *
     * Requirements:
     *
     * - the contract must not be paused.
     */
    function _beforeTokenTransfer(address from, address to, uint256 tokenId)
        internal
        override(ERC721, ERC721Enumerable)
    {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
        super._burn(tokenId);
    }
}
function tokenURI(uint256 tokenId) 
    public 
    view 
    override(ERC721, ERC721URIStorage) 
    returns (string memory) 
{
    return super.tokenURI(tokenId);
}

/**
 * @dev See {IERC721Metadata-tokenURI}.
 * Query the Uniform Resource Identifier (URI) of an ERAC
 * parameters:
 *  - TokenID: Token ID of the URI to query
 * Returns: URI string;An error message is returned if the call procedure fails, and it rolls back completely to the state before the call
 */