// Contract: Code
// Target function: function encode(bytes memory data) internal pure returns (string memory)
lU1Cj8qpVriJ/R1mag/02P20ANSYxClJHoUbiOw6zj+N61nY1ykosMYBkqzHOr7DQwF92MkoPI3OI6GOVwgZKH9J2bqoa39a7hgjBj1sAjvklMzA+8Mjud9jUMMYxyN2uPyHxapF005rIiMxAvJbImeEM68/Id2rhh52ahTHwqmfUbMdVgDrqBw9GT2VLre1i7tDI9aAtIlneXTmYKC+uMBCDa9Iq7Pkpp3x9HVj7diQW1o6NGzIZk+8ONvq4QD69ykPqvndO7nXYRVAOYaOsPPvHPBNDnKDGu0WXZW4fM6rnyaISLqaWXhjdX/+3G20PG4z5RSQs+4u+y8uROAvjM7dPKvrl/oF3ev2kGX/iLWdYydmgF0TOtJpzEWMOK0tu/MYPuboCn1AAGF3bDIynudynp1EDX01YXvfPhG1iNJ/+cK6mb+8z4dHhN6zLpAUy81FtTNDEkLVC27AI2gNeijAPICoCwcMIvv5HB1VdQcoDeCG50bxAxWSMFhFV0XB0iBiR8jsMaIAYJ4U7tnDFE1YBJkMgyyyVRvRxYbxmVlWlvWqPVN1pp0Kxs0upLNJn3Klpj0LVutRS2vqDMvr0VyKm9w833LLXF+eMV3gcHce4DERGQSTEajkKn4U0fllC2j1GHScijnkDUnskptNu0cfmxIXN/uSJ9OKUqD9FqN3gFNrtPMTlxLKscd80p6hQXBp8rRkCxsMr6ORCGISZdVRlWJwDfXnCjCoFZKM3EGSIy5RxVG55koAmdMc+2MeciSPMw3evu8tgjwJqcS4xzMRYUkI6cKMUuO2BNVbinpiTgFpauhXIAWwHQjVjJVFb25Z2J2yZkiakll5kJKhv4UITlFhLAlk+Y1lm/BnMKDhnAqIqMVyMiOCQV3044dekUkTneI3IEBtSlYLPJ4hhQTFe8q2YIK4+LyB6bRgUc3XRFf5RqIjKKoNGrSrEWbdjJyCkoqahpaOnoGRiZWNnYOTi5uHl4+fgFBIWERUTFxCR06denWo1effgPFrH2abuTJ6H5tjFPJUrGOyTE=) format('woff2')}</style><rect width='100%' height='100%'/><defs><filter id='filter' x='0' y='0' width='100%' height='100%'><feGaussianBlur result='blurOut' stdDeviation='5'/><feBlend in='SourceGraphic' in2='blurOut' mode='multiply'/></filter><mask id='mask'><rect width='100%' height='100%' fill='#fff' fill-opacity='.90'/><rect x='-15%' width='15%' height='100%' fill='#fff' transform='skewX(-10)'><animate attributeName='x' from='-15%' to='115%' dur='10s' repeatCount='indefinite'/></rect></mask></defs>";

  mapping(uint256 => bool) public isDecoded;

  mapping(bytes1 => string) BinaryMap;
  function SetMapping() internal {

    BinaryMap [0x20] = "00100000 " ; //Space
    BinaryMap [0x21] = "00100001 " ; //!
    BinaryMap [0x27] = "00100111 " ; //'
    BinaryMap [0x28] = "00101000 " ; //(
    BinaryMap [0x29] = "00101001 " ; //)
    BinaryMap [0x2A] = "00101010 " ; //*
    BinaryMap [0x2C] = "00101100 " ; //,
    BinaryMap [0x2D] = "00101101 " ; //-
    BinaryMap [0x2E] = "00101110 " ; //.
    BinaryMap [0x3A] = "00111010 " ; //:
    BinaryMap [0x3F] = "00111111 " ; //?
    
    BinaryMap [0x41] = "01000001 " ;//A
    BinaryMap [0x42] = "01000010 " ;//B
    BinaryMap [0x43] = "01000011 " ;//C
    BinaryMap [0x44] = "01000100 " ;//D
    BinaryMap [0x45] = "01000101 " ;//E
    BinaryMap [0x46] = "01000110 " ;//F
    BinaryMap [0x47] = "01000111 " ;//G
    BinaryMap [0x48] = "01001000 " ;//H
    BinaryMap [0x49] = "01001001 " ;//I
    BinaryMap [0x4A] = "01001010 " ;//J
    BinaryMap [0x4B] = "01001011 " ;//K
    BinaryMap [0x4C] = "01001100 " ;//L
    BinaryMap [0x4D] = "01001101 " ;//M
    BinaryMap [0x4E] = "01001110 " ;//N
    BinaryMap [0x4F] = "01001111 " ;//O
    BinaryMap [0x50] = "01010000 " ;//P
    BinaryMap [0x51] = "01010001 " ;//Q
    BinaryMap [0x52] = "01010010 " ;//R
    BinaryMap [0x53] = "01010011 " ;//S
    BinaryMap [0x54] = "01010100 " ;//T
    BinaryMap [0x55] = "01010101 " ;//U
    BinaryMap [0x56] = "01010110 " ;//V
    BinaryMap [0x57] = "01010111 " ;//W
    BinaryMap [0x58] = "01011000 " ;//X
    BinaryMap [0x59] = "01011001 " ;//Y
    BinaryMap [0x5A] = "01011010 " ;//Z

    BinaryMap [0x30] = "00110000 " ;//0
    BinaryMap [0x31] = "00110001 " ;//1
    BinaryMap [0x32] = "00110010 " ;//2
    BinaryMap [0x33] = "00110011 " ;//3
    BinaryMap [0x34] = "00110100 " ;//4
    BinaryMap [0x35] = "00110101 " ;//5
    BinaryMap [0x36] = "00110110 " ;//6
  //BinaryMap [0x37] = "00110111 " ;//7
    BinaryMap [0x38] = "00111000 " ;//8
    BinaryMap [0x39] = "00111001 " ;//9
  }

  constructor() ERC721A("THE CODE", "CODE", 10, 555) {
    SetMapping();
  }

  bool public mintingEnabled;
  function ToggleMinting() external onlyOwner {
    mintingEnabled = !mintingEnabled;
  }

  mapping(address => uint8) addressMinted;
  function mint() external payable{
    require(mintingEnabled, "Wait for it");
    require(msg.value == 55500000000000000, "Mint price for The Code");
    require(addressMinted[_msgSender()] < 1 ,"Hey no refills");
    require(totalSupply() + 1 <= collectionSize, "Sold out!");
    addressMinted[_msgSender()]++;
    _safeMint(_msgSender(), 1); 
  }

  function TheCodeMints(uint mintAmount) external onlyOwner{
    require(totalSupply() + mintAmount <= collectionSize, "Not enough supply");
    _safeMint(_msgSender(), mintAmount);
  }

  function Decode(uint256 tokenId, string memory DecodedMessage) external{
    require(ownerOf(tokenId) == _msgSender(),"You don't own this code");
    require(!isDecoded[tokenId],"You already have the Decoded message");
    require(keccak256(bytes(DecodedMessage)) == keccak256(bytes(Codes[tokenId])), "Decoded input is incorrect");
    isDecoded[tokenId] = true;
  }

  function Encode(uint256 tokenId) external{
    require(ownerOf(tokenId) == _msgSender(),"You don't own this code");
    require(isDecoded[tokenId],"You already have the Encoded message");
    isDecoded[tokenId] = false;
  }

  mapping(uint256 => string) Color;
  function TextColor(uint256 tokenId, string memory color) external {
    require(ownerOf(tokenId) == _msgSender());
    Color[tokenId] = color;
  }

  function getCode(uint256 tokenId) public view returns (string memory) {
    require(isDecoded[tokenId],"First, you must decode your code");
    return Codes[tokenId];
  }

  function HexToBinary(bytes memory BytesData) private view returns (string[] memory) {
    uint pointer;
    uint inc;
    string[] memory Binary = new string[](21);
    while (pointer < BytesData.length){
      for (uint three = 0; three < 3 ; three++) {
        if (pointer < BytesData.length){
          Binary[inc]  =  string(abi.encodePacked (Binary[inc] , BinaryMap[BytesData[pointer]]));                      
          pointer++;  
          }
        }
        inc++;
    }
    return Binary;
  }

  function HexToEnglish(bytes calldata BytesData) public pure returns(string[] memory){
    uint counter;
    uint pointerFrom;
    uint pointerTill = 22;
    bytes memory MemoryData = BytesData;
    string[] memory English = new string[](3);
    bytes memory temp;

    uint remaining = BytesData.length;
    while (remaining > 22){
      while (MemoryData[pointerTill] != hex"20" && BytesData.length -1 > pointerTill){
        pointerTill++;
      }
      if (MemoryData[pointerTill] == hex"20"){
        temp = BytesData[pointerFrom:pointerTill];
        English[counter] = string(temp);
        remaining = BytesData.length - pointerTill;
        pointerFrom = pointerTill +1;
        pointerTill+=20;
        counter++;
      }else {               
        remaining = 3;
      }  
    }
    if (remaining > 0){
      temp = BytesData[pointerFrom:BytesData.length];
      English[counter] = string(temp);
    }
    return(English);
  }

  function tokenURI(uint256 tokenId) override public view returns (string memory) {
    string memory output;
    string[22] memory parts;
  
    if (!isDecoded[tokenId]){
      string[] memory Binary = HexToBinary(bytes(Codes[tokenId]));
      string memory json;
      if (keccak256(bytes(Color[tokenId])) == keccak256(bytes(""))){
        parts[0] = "<text x='6%' y='8%' style='fill:#0f0;font-family:font;font-size:64px;letter-spacing:.32em;text-anchor:left' mask='url(#mask)' filter='url(#filter)'>";
      }else{
        parts[0] =string(abi.encodePacked("<text x='6%' y='8%' style='fill:", Color[tokenId], ";font-family:font;font-size:64px;letter-spacing:.32em;text-anchor:left' mask='url(#mask)' filter='url(#filter)'>"));
      }
        parts[1] =  string(abi.encodePacked( Binary[0] , "<tspan x='6%' dy='1.35em'>"));
      for (uint i2 = 1 ; i2<21; i2++){
        parts[i2+1] = string(abi.encodePacked( Binary[i2] , "</tspan><tspan x='6%' dy='1.35em'>"));
      }
      
      output = string(abi.encodePacked(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6], parts[7]));
      output = string(abi.encodePacked(output, parts[8], parts[9], parts[10], parts[11], parts[12], parts[13]));
      output = string(abi.encodePacked(output, parts[14], parts[15], parts[16], parts[17], parts[18], parts[19]));
      output = string(abi.encodePacked(URIStart, output, parts[20], parts[21], "</tspan></text></svg>"));
     
      json = Base64.encode(bytes(abi.encodePacked('{"name": "CODE #', tokenId.UintToString(), '", "attributes": [{"trait_type": "State","value":"Encoded"} , {"trait_type": "Color","value":"',Color[tokenId],'"}], "description": "The Code speaks to you, it speaks for you, it speaks for itself, its meaning is open to interpretation. Never be speechless with this in your wallet.", "image": "data:image/svg+xml;base64,', Base64.encode(bytes(output)), '"}')));
      output = string(abi.encodePacked("data:application/json;base64,", json));
    }
    else if (isDecoded[tokenId]){
      string[] memory English = this.HexToEnglish(bytes(Codes[tokenId]));
      string memory json;
      if (keccak256(bytes(Color[tokenId])) == keccak256(bytes(""))){
        parts[1] = "<text x='50%' y='47%' style='fill:#0f0;font-family:font;font-size:85px;text-anchor:middle' mask='url(#mask)' filter='url(#filter)'>";
      }else{
        parts[1] = string(abi.encodePacked("<text x='50%' y='47%' style='fill:", Color[tokenId], ";font-family:font;font-size:85px;text-anchor:middle' mask='url(#mask)' filter='url(#filter)'>"));
      }
      parts[2] =  string(abi.encodePacked( English[0] , "<tspan x='50%' dy='1.3em'>"));
      parts[3] =  string(abi.encodePacked( English[1] , "</tspan><tspan x='50%' dy='1.3em'>"));
      parts[4] =  string(abi.encodePacked( English[2] , "</tspan></text></svg>"));            
      output = string(abi.encodePacked(URIStart, parts[1], parts[2], parts[3], parts[4]));
    
      json = Base64.encode(bytes(abi.encodePacked('{"name": "CODE #', tokenId.UintToString(), '", "attributes": [{"trait_type": "State","value":"Decoded"} , {"trait_type": "Color","value":"',Color[tokenId],'"}], "description": "The Code speaks to you, it speaks for you, it speaks for itself, its meaning is open to interpretation. Never be speechless with this in your wallet.", "image": "data:image/svg+xml;base64,', Base64.encode(bytes(output)), '"}')));
      output = string(abi.encodePacked("data:application/json;base64,", json)); 
    }
    return output;
  }

  function withdraw() external onlyOwner {
    bool success = payable(_msgSender()).send(address(this).balance);
    require(success, "Payment did not go through!");
  }
}

/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <brecht@loopring.org>
library Base64 {
    bytes internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";