// Contract: Hazel
// Target function: function supportsInterface(bytes4 _interfaceID) public override pure returns (bool)
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";
        
        string memory docURI =  string.concat('<html><body><video autoplay controls src="data:video/mp4;base64,', videoURI, ' >',
                                    '</video></body></html>');
        bytes memory imageSvg = abi.encodePacked('"animation_url": "data:text/html;base64,', Base64.encode(bytes(docURI)),'",');
        return
            string(
                abi.encodePacked(
                    "data:application/json;base64,",
                    Base64.encode(
                        bytes(
                            abi.encodePacked(
                                '{"name":"Hazel","description":"0xHuskys dog. 100% onchain video",',
                                imageSvg,
                                '"attributes": []}'                                
                            )
                        )
                    )
                )
            );
    }

   

    /***********************************|
    |     Public Transfer Functions     |
    |__________________________________*/

    function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount, bytes memory _data)
        public override
    {
        require((msg.sender == _from) || isApprovedForAll(_from, msg.sender), "ERC1155#safeTransferFrom: INVALID_OPERATOR");
        require(_to != address(0),"ERC1155#safeTransferFrom: INVALID_RECIPIENT");

        _safeTransferFrom(_from, _to, _id, _amount);
        _callonERC1155Received(_from, _to, _id, _amount, gasleft(), _data);
    }

    function safeBatchTransferFrom(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data)
        public override
    {
        // Requirements
        require((msg.sender == _from) || isApprovedForAll(_from, msg.sender), "ERC1155#safeBatchTransferFrom: INVALID_OPERATOR");
        require(_to != address(0), "ERC1155#safeBatchTransferFrom: INVALID_RECIPIENT");

        _safeBatchTransferFrom(_from, _to, _ids, _amounts);
        _callonERC1155BatchReceived(_from, _to, _ids, _amounts, gasleft(), _data);
    }


    /***********************************|
    |    Internal Transfer Functions    |
    |__________________________________*/

    function _safeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount)
        internal
    {
        // Update balances
        balances[_from][_id] -= _amount;
        balances[_to][_id] += _amount;

        // Emit event
        emit TransferSingle(msg.sender, _from, _to, _id, _amount);
    }

    /**
    * @notice Verifies if receiver is contract and if so, calls (_to).onERC1155Received(...)
    */
    function _callonERC1155Received(address _from, address _to, uint256 _id, uint256 _amount, uint256 _gasLimit, bytes memory _data) internal {
        // Check if recipient is contract
        if (_to.code.length != 0) {
        bytes4 retval = IERC1155TokenReceiver(_to).onERC1155Received{gas: _gasLimit}(msg.sender, _from, _id, _amount, _data);
        require(retval == ERC1155_RECEIVED_VALUE, "ERC1155#_callonERC1155Received: INVALID_ON_RECEIVE_MESSAGE");
        }
    }

    function _safeBatchTransferFrom(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts) internal {
        require(_ids.length == _amounts.length, "ERC1155#_safeBatchTransferFrom: INVALID_ARRAYS_LENGTH");

        // Number of transfer to execute
        uint256 nTransfer = _ids.length;

        // Executing all transfers
        for (uint256 i = 0; i < nTransfer; i++) {
            
            balances[_from][_ids[i]] -= _amounts[i];
            balances[_to][_ids[i]]   += _amounts[i];
        }

        // Emit event
        emit TransferBatch(msg.sender, _from, _to, _ids, _amounts);
    }

    /**
    * @notice Verifies if receiver is contract and if so, calls (_to).onERC1155BatchReceived(...)
    */
    function _callonERC1155BatchReceived(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, uint256 _gasLimit, bytes memory _data) internal {
        // Pass data if recipient is contract
        if (_to.code.length != 0) {
        bytes4 retval = IERC1155TokenReceiver(_to).onERC1155BatchReceived{gas: _gasLimit}(msg.sender, _from, _ids, _amounts, _data);
        require(retval == ERC1155_BATCH_RECEIVED_VALUE, "ERC1155#_callonERC1155BatchReceived: INVALID_ON_RECEIVE_MESSAGE");
        }
    }


    /***********************************|
    |         Operator Functions        |
    |__________________________________*/


    function setApprovalForAll(address _operator, bool _approved)
        external override
    {
        // Update operator status
        operators[msg.sender][_operator] = _approved;
        emit ApprovalForAll(msg.sender, _operator, _approved);
    }

    function isApprovedForAll(address _owner, address _operator)
        public override view returns (bool isOperator)
    {
        return operators[_owner][_operator];
    }


    /***********************************|
    |         Balance Functions         |
    |__________________________________*/

    function balanceOf(address _owner, uint256 _id) public override view returns (uint256) {
        return balances[_owner][_id];
    }

    function balanceOfBatch(address[] memory _owners, uint256[] memory _ids) public override view returns (uint256[] memory) {
        require(_owners.length == _ids.length, "ERC1155#balanceOfBatch: INVALID_ARRAY_LENGTH");

        // Variables
        uint256[] memory batchBalances = new uint256[](_owners.length);

        // Iterate over each owner and token ID
        for (uint256 i = 0; i < _owners.length; i++) {
        batchBalances[i] = balances[_owners[i]][_ids[i]];
        }

        return batchBalances;
    }

    function uri(uint256 _id) public view returns (string memory) {
        return getTokenURI(_id);
    }

    function owner() external view returns(address own_) {
        own_ = admin;
    }