;; stackards-nft
;; NFT contract for stacks cards
;; https://cards.layerc.xyz
;; v5

;; (impl-trait 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait) ;; live
;; (impl-trait 'ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE.nft-trait.nft-trait) ;; test
(impl-trait .nft-trait.nft-trait)

;; (define-data-var admin-wallet principal 'ST19SAM5ASZ4MQ43NCGN1QQV1W4NR3QQDJ7BJP5BD)  ;; dc-3
(define-data-var admin-wallet principal 'SP3V11C6X2EBFN72RMS3B1NYQ1BX98F61GR6CFET9)  ;; max-1
;; (define-data-var admin-wallet principal 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5)

;; contract name
(define-non-fungible-token stackards-nft uint)


;; Store the last issues token ID
(define-data-var last-id uint u0)
(define-data-var mint-price uint u3)

;; admin-wallet can transfer tokens


;; this has to be the exact length of the string
(define-data-var meta-base-url (string-ascii 47) "https://cards.layerc.xyz/api/stackards/meta/v1/")
(define-data-var meta-url (string-ascii 47) "https://cards.layerc.xyz/api/tokens/cards/{id}")

;; data maps and vars

;; map tokenId: seed
(define-map seeds uint (string-ascii 64))

;; initializers

;; public functions

;; Claim a new NFT
(define-public (claim)
  (mint tx-sender))

;; claim NFT and store seed parameter
(define-public (meta-claim (seed (string-ascii 64)))
  (begin
    (match (mint tx-sender)
      success
        (begin
          (print "minted")
          (map-set seeds (var-get last-id) seed)
          (ok seed)
        )
      error (err error)
    )
  )
)

;; get seed for token id
(define-read-only (get-seed (token-id uint))
  (ok (map-get? seeds token-id)))


;; SIP009: Transfer token to a specified principal
;; the token-id has to be owned by the sender? validated inside nft-transfer
(define-public (transfer (token-id uint) (sender principal) (recipient principal))
  (if (and
        (is-eq tx-sender sender))
        (match (nft-transfer? stackards-nft token-id sender recipient)
          success (ok success)
          error (err error))
        (err u500)))

;; SIP009: Get the owner of the specified token ID
(define-read-only (get-owner (token-id uint))
  (ok (nft-get-owner? stackards-nft token-id)))

;; SIP009: Get the last token ID
(define-read-only (get-last-token-id)
  (ok (var-get last-id)))

;; SIP009: Get the token URI. You can set it to any other URI
;; (define-read-only (get-token-uri (token-id uint))
;;   (ok (some "https://stan.rik.ai/api/trees/1")))
(define-read-only (get-token-uri (token-id uint))
  (ok (some (concat (var-get meta-base-url) (uint-to-string token-id) ) ))
)

(define-read-only (get-meta-base (token-id uint))
  (ok (some (var-get meta-base-url) )))


(define-read-only (echo-int (token-id uint))
  (ok token-id))

;; private functions

;; Internal - Mint new NFT
(define-private (mint (new-owner principal))
    (let ((next-id (+ u1 (var-get last-id))))
      ;; Make sure to replace stackards-nft
      (match (nft-mint? stackards-nft next-id new-owner)
        success
          (begin
            (var-set last-id next-id)
            (print "minted")
            (print next-id)
            (ok true))
        error (err error))))



(define-read-only (get-caller)
  (begin
    (print contract-caller))
  )

(define-read-only (get-sender)
  (begin
    (print tx-sender)
  )
)

(define-read-only (get-mint-price)
  (begin
    (print (var-get mint-price))
    (ok (var-get mint-price))
  )
)

;; this is cos clarity doesn't have a concat string/int function
;; allows us to concat the string URL and int tokenID together
(define-constant LIST_40 (list
  true true true true true true true true true true
  true true true true true true true true true true
  true true true true true true true true true true
  true true true true true true true true true true
))

(define-read-only (uint-to-string (value uint))
  (get return (fold uint-to-string-clojure LIST_40 {value: value, return: ""}))
)

(define-read-only (uint-to-string-clojure (i bool) (data {value: uint, return: (string-ascii 40)}))
  (if (> (get value data) u0)
    {
      value: (/ (get value data) u10),
      return: (unwrap-panic (as-max-len? (concat (unwrap-panic (element-at "0123456789" (mod (get value data) u10))) (get return data)) u40))
    }
    data
  )
)

;; concat the string URL and int tokenID together
(define-read-only (get-token-string (tid uint))
  (ok
    (uint-to-string tid)
  )
)

;; check status on last mint
(define-read-only (mint-check)
  (print {evt: "mint-check", last: (var-get last-id), owner: tx-sender, amount: (var-get mint-price)})
)

;; allow admin wallets to transfer token to the user picking up the card
(define-public (admin-transfer (token-id uint) (sender principal) (recipient principal))
  (if (and
        (is-eq tx-sender (var-get admin-wallet)))
        (match (nft-transfer? stackards-nft token-id sender recipient)
          success (ok success)
          error (err error))
        (err u500)))


