pragma solidity ^0.8.4;







/*
    Manufactured by verdissage.

          .''..    ......       .....'.       ......    .....  ......                .....'..       ...............       .''.....'..                 
         .cooo;    'lool'      .collloc.      'lool'    ;oooc. .lool'                ,lolloo;.     .;oooollllllloo;.     .:olllllllo;.                
         .:ooo;    .lool'    .:cll,.,llc:.    'lool'    ;looc. .lool'             .,:co:'.:olc;.   .;oooc'......:ol:,. .;cll;.....;ol:;.              
         .cooo;    'lool'  ..:ll:,. .,:ll:..  'lool'    ;oooc. .lool'            .,clc;'  .;:ll,.. .;ooo:.      ;oooc. .lool'     .;;;,.              
         .cooo;    'lool' .:olo:.     .;ooo:. 'lool'    ;oooc. .lool'           'lool'      .coll, .;ooo:.      ;oooc. .lool'                         
         .,:co:'...;ll:;. .:oooc'.....':ooo:. .;:ll;....:oc:,. .lool'          'lool;......,lool, .:oooc'......,;;;,. .;:ll;.........                
            ,lollllloc.   .:oooollllllloooo:.   .:olllllll;.   .lool'           'looolllllllloool, .:oooollllllc'        .:olllllllllc.               
            ..;lool:'.    .:oooc,.....'cooo:.    .':lool;..    .lool'           'lool;......;lool, .:oooc,.....',;;;'.    .........;ll:;.             
              .cool,      .:ooo:.     .;ooo:.      ,looc.      .lool'           'lool'      .cool, .;ooo:.      ;oooc. .,,,,.      .cooo,             
              .cooo,      .:ooo:.     .;ooo:.      ,lool.      .lool;.........  'lool'      .cool, .;oooc'......:olc;. .:cll;......,loc:'             
              .cooo,      .:ooo:.     .;ooo:.      ,lool.      .looolllllllllc' 'lool'      .cool, .;oooollllllllo;.     .:ollllllllol'               
               .'''.       .'''.       .'''.       .''''.      .''''''''''''''. .''''.      ..'''.  .'''''''''''''.       .''''''''''.  
*/                            
/// @custom:security-contact snoo@yaylabs.io
/// Version 0.2. 11.11.2022
contract SBT1_EduCarrillo is ERC721, ERC721Enumerable, ERC721Burnable, Ownable {
    using Counters for Counters.Counter;
    using Strings for uint256;

    struct Art{
        bool isActive;//mint 매핑시 지워도 되는 값인지 판단. When burned, it changed to false value.
        uint256 tokenId;
        string artImageUrl;
    }

    event Mint(address _to, uint256 _artNumber, uint256 _tokenId);
    event SetArtToToken(uint256 _artNumber, uint256 _tokenId, string _artImageUrl);
    event SetBaseUri(string _baseUri);

    Counters.Counter private _tokenIdCounter;

    string public artist;
    uint256 public round;
    string public date;
    uint256 public artMaxCount;
    string public baseUri = '';
    mapping(uint256 => Art) public artList; //art number mapping to tokenId (unique mapping)
    mapping(uint256 => uint256) public tokenToArt;

    constructor(string memory _artist, uint256 _round, string memory _date, uint256 _artMaxCount, string memory _baseUri) ERC721("SBT1_EduCarrillo", "ADSBT_EDUCARRILLO") {
        artist = _artist;
        round = _round;
        date = _date;
        artMaxCount = _artMaxCount;
        baseUri = _baseUri;
    }

    function safeMint(address _to, uint256 _artNumber, string memory artImageUrl) public onlyOwner {
        require(_artNumber <= artMaxCount, 'artNumber must be less than artMaxCount');
        uint256 tokenId = _tokenIdCounter.current() + 1;
        _safeMint(_to, tokenId);
        setArtToToken(_artNumber, tokenId, artImageUrl);
        _tokenIdCounter.increment();
        emit Mint(_to, _artNumber, tokenId);
    }

    function setArtToToken(uint256 _artNumber, uint256 _tokenId, string memory _artImageUrl) private onlyOwner {
        require(bytes(_artImageUrl).length > 0, 'artImageURl must be longer than 0');
        require(artList[_artNumber].isActive != true, 'the artwork is already minted');
        artList[_artNumber].isActive = true;
        artList[_artNumber].tokenId = _tokenId;
        artList[_artNumber].artImageUrl = _artImageUrl;
        tokenToArt[_tokenId] = _artNumber;
        emit SetArtToToken(_artNumber, _tokenId, _artImageUrl);
    }

    function _getArtStruct(uint256 _artNumber) public view returns(Art memory){
        require(_artNumber <= artMaxCount, 'artNumber must be less than artMaxCount!');
        return artList[_artNumber];
    }
    
    function _getArtImageUrl(uint256 _artNumber) public view returns(string memory){
        require(artList[_artNumber].isActive == true, 'the artNumber is not minted!');
        return artList[_artNumber].artImageUrl;
    }

    function setBaseUri(string memory _baseUri) public onlyOwner {
        require(bytes(_baseUri).length > 0, '_baseUri length must be longer than 0');
        baseUri = _baseUri;
        emit SetBaseUri(_baseUri);
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId)
        internal
        override(ERC721, ERC721Enumerable)
    {
        require(from == address(0), 'Err: token transfer is BLOCKED');
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function _burn(uint256 tokenId) internal override(ERC721) {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721)
        returns (string memory)
    {
        require(_exists(tokenId), 'ERC721Metadata: URI query for nonexistent token');
        uint256 artNumber = tokenToArt[tokenId];
        return string(abi.encodePacked(baseUri, artNumber.toString(), '.json'));
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721Enumerable)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}
[{"inputs":[{"internalType":"string","name":"_artist","type":"string"},{"internalType":"uint256","name":"_round","type":"uint256"},{"internalType":"string","name":"_date","type":"string"},{"internalType":"uint256","name":"_artMaxCount","type":"uint256"},{"internalType":"string","name":"_baseUri","type":"string"}],"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":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_artNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Mint","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":false,"internalType":"uint256","name":"_artNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"_artImageUrl","type":"string"}],"name":"SetArtToToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_baseUri","type":"string"}],"name":"SetBaseUri","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"},{"inputs":[{"internalType":"uint256","name":"_artNumber","type":"uint256"}],"name":"_getArtImageUrl","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_artNumber","type":"uint256"}],"name":"_getArtStruct","outputs":[{"components":[{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"artImageUrl","type":"string"}],"internalType":"struct SBT1_EduCarrillo.Art","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"artList","outputs":[{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"artImageUrl","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"artMaxCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"artist","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"date","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":[{"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":[],"name":"round","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_artNumber","type":"uint256"},{"internalType":"string","name":"artImageUrl","type":"string"}],"name":"safeMint","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":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseUri","type":"string"}],"name":"setBaseUri","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":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenToArt","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":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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"}]