pragma solidity ^0.8.10;










contract Fomo3dInscription is ERC721,Ownable{
    uint256 private _nextTokenId;
    using Strings for uint256;
    using Counters for Counters.Counter;
    Counters.Counter public _tokenIds;
    string description;

    mapping(uint256 => uint256) public tokenIdToLevels;
    mapping (uint => string) public saySomethingHere;
    mapping (uint => string) public saySomethingHere1;
    mapping (uint => string) public saySomethingHere2;
    mapping (address => uint) public userMintedAmount;

    //mapping (uint => uint) public originNftId;//tokenId => nftId

    Ifomo3d fomo;

    event refreshMetadata(uint indexed tokenId);



    constructor(string memory _name, string memory _description,address _fomo)
        ERC721(_name, "ethf")
    {
        description = _description;
        fomo = Ifomo3d(_fomo);


    }


    // The following functions are overrides required by Solidity.





    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }



    function generateCharacter(uint256 tokenId) public view returns(string memory){

        return string(
        abi.encodePacked(
            "data:image/svg+xml;base64,",
            Base64.encode(generateCharacter5(tokenId))
        )    
        );
    }

    function generateCharacter1(uint256 tokenId) internal view returns(bytes memory){

        bytes memory svg1 = abi.encodePacked(
        '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 500 500">',
        '<style>.base { fill: yellow; font-family: serif; font-size: 25px; }</style>',
        '<rect width="100%" height="100%" fill="blue" />',
        '<text x="50%" y="30%" class="base" dominant-baseline="middle" text-anchor="middle" font-weight="bold">', "inscription",'</text>'
        '<text x="50%" y="40%" class="base" dominant-baseline="middle" text-anchor="middle" font-weight="bold">',"tick: ",name(),'</text>',
        '<text x="50%" y="50%" class="base" dominant-baseline="middle" text-anchor="middle" font-weight="bold">', "amount: ",getLevels(tokenId),'</text>',
        ''
        );
        return svg1;
    }

    function generateCharacter2(uint256 tokenId) internal view returns(bytes memory){

        bytes memory svg2;
        svg2 = abi.encodePacked(generateCharacter1(tokenId),
        '<text x="50%" y="10%" class="base" dominant-baseline="middle" text-anchor="middle" font-weight="bold">', "Id: ",tokenId.toString(),'</text>',
        ''
        );
        return svg2;
    }
    //<text x="10" y="40" style="font-family: Arial; font-size: 20px; fill: black;">Hello, SVG!</text>
    function generateCharacter3(uint256 tokenId) internal view returns(bytes memory){
        bytes memory svg3;
        svg3 = abi.encodePacked(generateCharacter2(tokenId),
        '<text x="50%" y="70%" font-family="Arial" font-size="20" fill = "red" text-anchor="middle" alignment-baseline="middle" font-weight="bold">',saySomethingHere[tokenId],'</text>'
        //'<text x="50%" y="90%" font-family="Arial" font-size="10" fill = "white" text-anchor="middle" alignment-baseline="middle">',userComment1[tokenId],'</text>'
        ''
        );

        
        return svg3;
    }

    function generateCharacter4(uint256 tokenId) internal view returns(bytes memory){
        bytes memory svg4;
        svg4 = abi.encodePacked(generateCharacter3(tokenId),
        '<text x="50%" y="80%" font-family="Arial" font-size="20" fill = "red" text-anchor="middle" alignment-baseline="middle" font-weight="bold">',saySomethingHere1[tokenId],'</text>'
        //'<text x="50%" y="90%" font-family="Arial" font-size="10" fill = "white" text-anchor="middle" alignment-baseline="middle">',userComment1[tokenId],'</text>'
        ''
        );

        
        return svg4;
    }

    function generateCharacter5(uint256 tokenId) internal view returns(bytes memory){
        bytes memory svg5;
        svg5 = abi.encodePacked(generateCharacter4(tokenId),
        '<text x="50%" y="90%" font-family="Arial" font-size="20" fill = "red" text-anchor="middle" alignment-baseline="middle" font-weight="bold">',saySomethingHere2[tokenId],'</text>'
        //'<text x="50%" y="90%" font-family="Arial" font-size="10" fill = "white" text-anchor="middle" alignment-baseline="middle">',userComment1[tokenId],'</text>'
        '</svg>'
        );

        
        return svg5;
    }





    function addrToString(address addr) public pure returns (string memory) {
        return uint256(uint160(addr)).toString();
    }

    function getLevels(uint256 tokenId) public view returns (string memory) {
        uint256 levels = tokenIdToLevels[tokenId];
        return levels.toString();
    }

    function getLevels_Num(uint256 tokenId) public view returns (uint) {
        uint256 levels = tokenIdToLevels[tokenId];
        return levels;
    }

    function tokenURI(uint256 tokenId) public override view returns (string memory){
        bytes memory dataURI = abi.encodePacked(
        '{',
            '"name": "inscription #', tokenId.toString(), '",',
            '"description": "inscription",',
            '"image": "', generateCharacter(tokenId), '"',
        '}'
        );
        return string(
        abi.encodePacked(
            "data:application/json;base64,",
            Base64.encode(dataURI)
        )
        );
    }

    function inscribe() public  {
        require(_tokenIds.current() < 21000,"max");
        uint _amount = getBalance();
        require(_amount>0,"amount is 0");
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
        _safeMint(msg.sender, newItemId);
        tokenIdToLevels[newItemId] = 1000;

        userMintedAmount[msg.sender] += 1000;
    }

    function inscribeForAmount(uint amount) public {
        for(uint i; i < amount; i++){
            inscribe();
        }
    }

    function initialInscription(uint tokenId,string memory _something1,string memory _something2,string memory _something3) public {
        write1(tokenId,_something1);
        write2(tokenId,_something2);
        write3(tokenId,_something3);
    }






    function getBalance()public view returns (uint){
        return fomo.balance(msg.sender) - userMintedAmount[msg.sender];
    }


    function write1(uint tokenId,string memory _something)public {
        require(ownerOf(tokenId) == msg.sender,"not owner");
        saySomethingHere[tokenId] = _something;

        emit refreshMetadata(tokenId);
    }

    function write2(uint tokenId,string memory _something)public{
        require(ownerOf(tokenId) == msg.sender,"not owner");
        saySomethingHere1[tokenId] = _something;

        emit refreshMetadata(tokenId);
    }
    function write3(uint tokenId,string memory _something)public {
        require(ownerOf(tokenId) == msg.sender,"not owner");
        saySomethingHere2[tokenId] = _something;

        emit refreshMetadata(tokenId);
    }


    function burn(uint _tokenId) public {
        require(ownerOf(_tokenId) == msg.sender,"no owner");
        _burn(_tokenId);
    }


}
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_description","type":"string"},{"internalType":"address","name":"_fomo","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"refreshMetadata","type":"event"},{"inputs":[],"name":"_tokenIds","outputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"addrToString","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"generateCharacter","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getLevels","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getLevels_Num","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"_something1","type":"string"},{"internalType":"string","name":"_something2","type":"string"},{"internalType":"string","name":"_something3","type":"string"}],"name":"initialInscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inscribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"inscribeForAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"saySomethingHere","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"saySomethingHere1","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"saySomethingHere2","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenIdToLevels","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userMintedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"_something","type":"string"}],"name":"write1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"_something","type":"string"}],"name":"write2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"_something","type":"string"}],"name":"write3","outputs":[],"stateMutability":"nonpayable","type":"function"}]