contract NiftyBuilderInstance is ERC721, ERC721Burnable {

    // Engine of nifty type dynamism.
    address public _dateTimeContract;

    string[24] artifact = [
        "QmX8iUovtYAnW55CQsLdVTE5WpQrR57MU4zaofZ1D52Hj8", // State 21
        "QmVZpXKZAnDHb2VvcSy7xsSJkrpooMVjxNKWuvFq3DkNsR", // State 22
        "QmcARhBGo5berbpxJwDwUMh8dJ5NRQTcRmXgvxcztfNFAC", // State 23
        "Qma3gJpKVqVCwuau9km6tdMpY5C7FGwZ4ccesuKCvmA5NK", // State 00
        "QmQaaApgJ78SvA2BmzuPiPAAf1WXjhLMHDP49QU3Xf8zyP", // State 01
        "QmPDpUWmbaKmKTztMUWiqCK7gyGAxJmmHnAQ7mtg6R8H5k", // State 02
        "QmQ8P9wHmmVL8eDbqKy9cU2FjoAgUzWFfJQrf9zj97Ybvd", // State 03
        "QmRcNwBvweTMuR2MWqFYXgEvuN95YXaLgDjFVMkXfHgAcf", // State 04
        "QmYrkxdwdaR5obbpzgyt1fXjXAmL49eRX711byuwpkSyHF", // State 05
        "QmYkm9vYws9P9nnCDLoRj3b2m1LcGiPebkRPph5n4tcmkQ", // State 06
        "QmW3PAYr38ZFm8McgoDeWEjySZgg71r3CefLxqzxVb9e9e", // State 07
        "QmW72F3RumxejwY371VdCXjN8CZcqTSzBpJPvF9qzuZ2Ga", // State 08
        "QmcExNFJzEpceBStuc4qqu4zQ9UvMCTtywzxgVj569Toh4", // State 09
        "QmNeSYYC23ejs4bk46Df6XHoWXHE3ttAoXZ8bAWWaFFmTW", // State 10
        "QmNMHfJi5qCzxmKVMqoq7vA2wJ7ao72YfdxNg5oFwnyTSU", // State 11
        "QmaaXjPJsdewHifYKEheq6xbwrq126s57NBZ1AcjYHEhG9", // State 12
        "QmPYE5ZYSK3vnD54tzJRuPybsXmeEbcUwV1jMwS47iENwE", // State 13
        "Qmea2kv6QfmTxpkQF3u1TbAF4h9ixZjp5fLvCzc4HZua7t", // State 14
        "QmPm9yiVYJysG7QuqFFw7HiEUE3HWrTDKM6j7TSLF2nmHG", // State 15
        "QmZsQq4jVLyr7xa3ATxffrDLJAm88dhZQ9PGUpDyPgJ8YX", // State 16
        "QmYvedoVgGFJFMkRCMbLosr2yjMSF77Yvkf7SA1QNGbvxv", // State 17
        "QmYDhG4jpsULynxyxF71ZRFR5d5KJqsFvzN5FDxtbtg7Zi", // State 18
        "QmTypKxYfqBeN3ruGE3FsWBSfBVdcwf2B3qLeb4c4qvMyp", // State 19
        "QmRzi62hYnV2ErQ9WwDQpoYL7ZPibpGBzjy6amu8ghC8yB"  // State 20
    ];

    // The artist associated with the collection.
    string private _creator;

    // Number of NFTs minted for a given 'typeCount'. 
    mapping (uint256 => uint256) public _mintCount;

    /**
     * @dev Serves as a gas cost optimized boolean flag 
     * to indicate whether the minting process has been 
     * concluded for a given 'typeCount', correspinds 
     * to the {_getFinalized} and {setFinalized}.
     */
    mapping (uint256 => bytes32) private _finalized;

    /**
     * @dev Emitted when tokens are created.
     */
    event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed fromAddress, address indexed toAddress);

    /**
     * @dev Ultimate instantiation of a Nifty Gateway NFT collection. 
     */
    constructor() ERC721() {
        _creator = "Six N. Five";
        _dateTimeContract = 0x740a637ADD6492e5FaA907AF0fe708770B737058; //Mainnet
        // _dateTimeContract = 0x92482Ba45A4D2186DafB486b322C6d0B88410FE7; //Rinkeby
        _setNiftyTypeName(1, "Eternal Wait");
    }

    /**
     * Configurable address for DateTime.
     */ 
    function setDateTimeContract(address dateTimeContract_) public onlyValidSender {
        _dateTimeContract = dateTimeContract_;
    }

    /**
     * @dev Generate canonical Nifty Gateway token representation. 
     * Nifty contracts have a data model called a 'niftyType' (typeCount) 
     * The 'niftyType' refers to a specific nifty in our contract, note 
     * that it gives no information about the edition size. In a given 
     * contract, 'niftyType' 1 could be an edition of 10, while 'niftyType' 
     * 2 is a 1/1, etc.
     * The token IDs are encoded as follows: {id}{niftyType}{edition #}
     * 'niftyType' has 4 digits, and edition number does as well, to allow 
     * for 9999 possible 'niftyType' and 9999 of each edition in each contract.
     * Example token id: [500010270]
     * This is from contract #5, it is 'niftyType' 1 in the contract, and it is 
     * edition #270 of 'niftyType' 1.
     */
    function _encodeTokenId(uint256 niftyType, uint256 tokenNumber) private view returns (uint256) {
        return (topLevelMultiplier + (niftyType * midLevelMultiplier) + tokenNumber);
    }

    /**
     * @dev Determine whether it is possible to mint additional NFTs for this 'niftyType'.
     */
    function _getFinalized(uint256 niftyType) public view returns (bool) {
        bytes32 chunk = _finalized[niftyType / 256];
        return (chunk & bytes32(1 << (niftyType % 256))) != 0x0;
    }

    /**
     * @dev Prevent the minting of additional NFTs of this 'niftyType'.
     */
    function setFinalized(uint256 niftyType) public onlyValidSender {
        uint256 quotient = niftyType / 256;
        bytes32 chunk = _finalized[quotient];
        _finalized[quotient] = chunk | bytes32(1 << (niftyType % 256));
    }

    /**
     * @dev The artist of this collection.
     */
    function creator() public view virtual returns (string memory) {
        return _creator;
    }

    /**
     * @dev Assign the root location where the artifact assets are stored.
     */
    function setBaseURI(string memory baseURI) public onlyValidSender {
        _setBaseURI(baseURI);
    }

    /**
     * @dev Allow owner to change nifty name, by 'niftyType'.
     */
    function setNiftyName(uint256 niftyType, string memory niftyName) public onlyValidSender {
        _setNiftyTypeName(niftyType, niftyName);
    }

    /**
     * @dev Assign the IPFS hash of canonical artifcat file, by 'niftyType'.
     */   
    function setNiftyIPFSHash(uint256 niftyType, string memory hashIPFS) public onlyValidSender {
        _setTokenIPFSHashNiftyType(niftyType, hashIPFS);
    }

    /**
     * @dev Create specified number of nifties en masse.
     * Once an NFT collection is spawned by the factory contract, we make calls to set the IPFS
     * hash (above) for each Nifty type in the collection. 
     * Subsequently calls are issued to this function to mint the appropriate number of tokens 
     * for the project.
     */
    function mintNifty(uint256 niftyType, uint256 count) public onlyValidSender {
        require(!_getFinalized(niftyType), "NiftyBuilderInstance: minting concluded for nifty type");
            
        uint256 tokenNumber = _mintCount[niftyType] + 1;
        uint256 tokenId00 = _encodeTokenId(niftyType, tokenNumber);
        uint256 tokenId01 = tokenId00 + count - 1;
        
        for (uint256 tokenId = tokenId00; tokenId <= tokenId01; tokenId++) {
            _owners[tokenId] = _defaultOwner;
        }
        _mintCount[niftyType] += count;
        _balances[_defaultOwner] += count;

        emit ConsecutiveTransfer(tokenId00, tokenId01, address(0), _defaultOwner);
    }

    /**
     * @dev Returns an IPFS hash for a given token ID.
     * Throws if the token ID does not exist. May return an empty string.
     * @param tokenId uint256 ID of the token to query.
     * @return IPFS hash for this (_typeCount) NFT. 
     */
    function tokenIPFSHash(uint256 tokenId) external view returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: IPFS hash query for nonexistent token");
        uint8 hour = IDateTime(_dateTimeContract).getHour(block.timestamp);
        return artifact[hour];
    }

}
/** 
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  .***   XXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  ,*********  XXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXX  ***************  XXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXX  .*******************  XXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXX  ***********    **********  XXXXXXXX
 * XXXXXXXXXXXXXXXXXXXX   ***********       ***********  XXXXXX
 * XXXXXXXXXXXXXXXXXX  ***********         ***************  XXX
 * XXXXXXXXXXXXXXXX  ***********           ****    ********* XX
 * XXXXXXXXXXXXXXXX *********      ***    ***      *********  X
 * XXXXXXXXXXXXXXXX  **********  *****          *********** XXX
 * XXXXXXXXXXXX   /////.*************         ***********  XXXX
 * XXXXXXXXX  /////////...***********      ************  XXXXXX
 * XXXXXXX/ ///////////..... /////////   ///////////   XXXXXXXX
 * XXXXXX  /    //////.........///////////////////   XXXXXXXXXX
 * XXXXXXXXXX .///////...........//////////////   XXXXXXXXXXXXX
 * XXXXXXXXX .///////.....//..////  /////////  XXXXXXXXXXXXXXXX
 * XXXXXXX# /////////////////////  XXXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXX   ////////////////////   XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XX   ////////////// //////   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 *
 * @dev Nifty Gateway extension of customized NFT contract, encapsulates
 * logic for minting new tokens, and concluding the minting process. 
 */
function setDateTimeContract(address dateTimeContract_) public onlyValidSender {
    _dateTimeContract = dateTimeContract_;
}

/**
 * Configurable address for DateTime.
 */