(mod (
    NFT_STATE_LAYER_MOD_HASH
    METADATA
    METADATA_UPDATER_PUZZLE_HASH
    INNER_PUZZLE
    inner_solution
  )

  (include condition_codes.clib)
  (include curry-and-treehash.clib)
  (include utility_macros.clib)

  (defun-inline nft_state_layer_puzzle_hash (NFT_STATE_LAYER_MOD_HASH METADATA METADATA_UPDATER_PUZZLE_HASH inner_puzzle_hash)
    (puzzle-hash-of-curried-function NFT_STATE_LAYER_MOD_HASH
                                     inner_puzzle_hash
                                     (sha256 ONE METADATA_UPDATER_PUZZLE_HASH)
                                     (sha256tree METADATA)
                                     (sha256 ONE NFT_STATE_LAYER_MOD_HASH)
    )
  )


  ; this function does two things - it wraps the odd value create coins, and it also filters out all negative conditions
  ; odd_coin_params is (puzhash amount ...)
  ; new_metadata_info is ((METADATA METADATA_UPDATER_PUZZLE_HASH) conditions)
  (defun wrap_odd_create_coins (NFT_STATE_LAYER_MOD_HASH conditions odd_coin_params new_metadata_info metadata_seen)
    (if conditions
      (if (= (f (f conditions)) CREATE_COIN)
          (if (logand (f (r (r (f conditions)))) ONE)
              (assert (not odd_coin_params)
                (wrap_odd_create_coins NFT_STATE_LAYER_MOD_HASH (r conditions) (r (f conditions)) new_metadata_info metadata_seen)
              )
              (c (f conditions) (wrap_odd_create_coins NFT_STATE_LAYER_MOD_HASH (r conditions) odd_coin_params new_metadata_info metadata_seen))
          )
          (if (= (f (f conditions)) -24)
              (wrap_odd_create_coins NFT_STATE_LAYER_MOD_HASH (r conditions) odd_coin_params
                (assert (all
                          (= (sha256tree (f (r (f conditions)))) (f (r (f new_metadata_info))))
                          (not metadata_seen)
                        )
                    ; then
                    (a (f (r (f conditions))) (list (f (f new_metadata_info)) (f (r (f new_metadata_info))) (f (r (r (f conditions))))))
                )
                ONE  ; the metadata update has been seen now
              )
              (c (f conditions) (wrap_odd_create_coins NFT_STATE_LAYER_MOD_HASH (r conditions) odd_coin_params new_metadata_info metadata_seen))
          )
      )
      (c
        (c CREATE_COIN
            (c
              (nft_state_layer_puzzle_hash
                NFT_STATE_LAYER_MOD_HASH
                (f (f new_metadata_info))
                (f (r (f new_metadata_info)))
                (f odd_coin_params)  ; metadata updater solution
              )
              (r odd_coin_params)
            )
        )
        (f (r new_metadata_info))  ; metadata_updater conditions
      )
    )
  )

  ; main
  (wrap_odd_create_coins
    NFT_STATE_LAYER_MOD_HASH
    (a INNER_PUZZLE inner_solution)
    ()
    (list (list METADATA METADATA_UPDATER_PUZZLE_HASH) 0)  ; if the magic condition is never seen, this is the information we us to recurry
    ()
  )
)
