contract Words is IWords, ERC721, IERC721Metadata {
    string public override name = "Words";
    string public override symbol = "WORDS";

    uint256 public tokenId;

    mapping(uint256 => string) public text;

    function mint(string memory text_) external override returns (uint256) {
        _mint(msg.sender, tokenId);

        text[tokenId] = text_;

        return tokenId++;
    }

    // Mostly looted from Loot: https://etherscan.io/address/0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7#code
    function tokenURI(uint256 tokenId_)
        external
        view
        override
        returns (string memory)
    {
        require(_exists(tokenId_), "nonexistent token");

        string[3] memory parts;
        parts[
            0
        ] = '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350"><style>.base { fill: white; font-family: serif; font-size: 14px; }</style><rect width="100%" height="100%" fill="black" /><text x="10" y="20" class="base">';
        parts[1] = text[tokenId_];
        parts[2] = "</text></svg>";

        string memory output = string(
            abi.encodePacked(parts[0], parts[1], parts[2])
        );
        string memory json = Base64.encode(
            bytes(
                string(
                    abi.encodePacked(
                        '{"name": "TokenId #',
                        toString(tokenId_),
                        '", "description": "Test", "image": "data:image/svg+xml;base64,',
                        Base64.encode(bytes(output)),
                        '"}'
                    )
                )
            )
        );
        output = string(
            abi.encodePacked("data:application/json;base64,", json)
        );
        return output;
    }

    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT license
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }
}
/**
 * @title Words
 * @author MirrorXYZ
 */
function tokenURI(uint256 tokenId_)
    external
    view
    override
    returns (string memory)
{
    require(_exists(tokenId_), "nonexistent token");

    string[3] memory parts;
    parts[
        0
    ] = '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350"><style>.base { fill: white; font-family: serif; font-size: 14px; }</style><rect width="100%" height="100%" fill="black" /><text x="10" y="20" class="base">';
    parts[1] = text[tokenId_];
    parts[2] = "</text></svg>";

    string memory output = string(
        abi.encodePacked(parts[0], parts[1], parts[2])
    );
    string memory json = Base64.encode(
        bytes(
            string(
                abi.encodePacked(
                    '{"name": "TokenId #',
                    toString(tokenId_),
                    '", "description": "Test", "image": "data:image/svg+xml;base64,',
                    Base64.encode(bytes(output)),
                    '"}'
                )
            )
        )
    );
    output = string(
        abi.encodePacked("data:application/json;base64,", json)
    );
    return output;
}

// Mostly looted from Loot: https://etherscan.io/address/0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7#code