(define-library (lib curl)
   (import (otus lisp)
           (otus ffi))
   (export
      curl_easy_init
      curl_easy_setopt
         CURLOPT_WRITEDATA     ; This is the FILE * or void * the regular output should be written to
         CURLOPT_URL           ; The full URL to get/put
         CURLOPT_WRITEFUNCTION ; 
      curl_easy_reset
      curl_easy_perform
      
      curl_easy_cleanup
      
      curl_global_init
         CURL_GLOBAL_SSL ; no meaning since 7.57.0
         CURL_GLOBAL_WIN32 ; Initialize the Win32 socket libraries
         CURL_GLOBAL_ALL ; Initialize everything possible
         CURL_GLOBAL_NOTHING ; Initialise nothing extra
         CURL_GLOBAL_DEFAULT ; A sensible default, it will init both SSL and Win32
         CURL_GLOBAL_ACK_EINTR ; has no point since 7.69.0

      ; high level lisp API
      make-curl
   )

(cond-expand
   ((or Linux Android)
      (begin
         (define libcurl (load-dynamic-library "libcurl.so.4"))))
   (Windows
      (begin
         (define libcurl (load-dynamic-library "libcurl.dll")))))

(begin
   ;; (define OBJECTPOINT   10000)
   ;; (define STRINGPOINT   OBJECTPOINT)
   ;; (define SLISTPOINT    OBJECTPOINT)
   ;; (define FUNCTIONPOINT 20000)
   ;; (define (CINIT tt number)
   ;;    (+ tt number))


   (setq CURL* fft-void*)
   (setq CURLcode fft-int)
   (setq CURLoption fft-int)
      (define CURLOPT_WRITEDATA     10001)    (define CURLOPT_FILE CURLOPT_WRITEDATA)
      (define CURLOPT_URL           10002)
      (define CURLOPT_PORT              3)
      (define CURLOPT_PROXY         10004)
      (define CURLOPT_USERPWD       10005)
      (define CURLOPT_PROXYUSERPWD  10006)
      (define CURLOPT_RANGE         10007)
      (define CURLOPT_READDATA      10009)    (define CURLOPT_INFILE CURLOPT_READDATA)
      (define CURLOPT_ERRORBUFFER   10010)
      (define CURLOPT_WRITEFUNCTION 20011)
      (define CURLOPT_READFUNCTION  20012)
      (define CURLOPT_TIMEOUT          13)
      (define CURLOPT_INFILESIZE       14)
      (define CURLOPT_POSTFIELDS    10015)
      (define CURLOPT_REFERER       10016)
      (define CURLOPT_FTPPORT       10017)
      (define CURLOPT_USERAGENT     10018)
      (define CURLOPT_LOW_SPEED_LIMIT  19)
      (define CURLOPT_LOW_SPEED_TIME   20)
      (define CURLOPT_RESUME_FROM      21)
      (define CURLOPT_COOKIE        10022)
      (define CURLOPT_HTTPHEADER    10023)
      (define CURLOPT_HTTPPOST      10024)
      (define CURLOPT_SSLCERT       10025)
      (define CURLOPT_KEYPASSWD     10026)
      (define CURLOPT_CRLF             27)
      (define CURLOPT_QUOTE         10028)
      (define CURLOPT_HEADERDATA    10029)    (define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA)
      (define CURLOPT_COOKIFIL      10031)
      (define CURLOPT_SSLVERSION       32)
      (define CURLOPT_TIMECONDITION    33)
      (define CURLOPT_TIMEVALUE        34)
      (define CURLOPT_CUSTOMREQUEST 10036)
      (define CURLOPT_STDERR        10037)
      (define CURLOPT_POSTQUOTE     10039)
      (define CURLOPT_OBSOLETE40    10040)
      (define CURLOPT_VERBOSE          41)
      (define CURLOPT_HEADER           42)
      (define CURLOPT_NOPROGRESS       43)
      (define CURLOPT_NOBODY           44)
      (define CURLOPT_FAILONERROR      45)
      (define CURLOPT_UPLOAD           46)
      (define CURLOPT_POST             47)
      (define CURLOPT_DIRLISTONLY      48)
      (define CURLOPT_APPEND           50)
      (define CURLOPT_NETRC            51)
      (define CURLOPT_FOLLOWLOCATION   52)
      (define CURLOPT_TRANSFERTEXT     53)
      (define CURLOPT_PUT              54)
      (define CURLOPT_PROGRESSFUNCTION 20056)
      (define CURLOPT_PROGRESSDATA  10057)    (define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA)
      (define CURLOPT_AUTOREFERER    58)
      (define CURLOPT_PROXYPORT    59)
      (define CURLOPT_POSTFIELDSIZE    60)
      (define CURLOPT_HTTPPROXYTUNNEL    61)
      (define CURLOPT_INTERFACE 10062)
      (define CURLOPT_KRBLEVEL 10063)
      (define CURLOPT_SSL_VERIFYPEER    64)
      (define CURLOPT_CAINFO 10065)
      (define CURLOPT_MAXREDIRS    68)
      (define CURLOPT_FILETIME    69)
      (define CURLOPT_TELNETOPTIONS 10070)
      (define CURLOPT_MAXCONNECTS    71)
      (define CURLOPT_OBSOLETE72    72)
      (define CURLOPT_FRESH_CONNECT    74)
      (define CURLOPT_FORBID_REUSE    75)
      (define CURLOPT_RANDOM_FILE 10076)
      (define CURLOPT_EGDSOCKET 10077)
      (define CURLOPT_CONNECTTIMEOUT    78)
      (define CURLOPT_HEADERFUNCTION 20079)
      (define CURLOPT_HTTPGET    80)
      (define CURLOPT_SSL_VERIFYHOST    81)
      (define CURLOPT_COOKIEJAR 10082)
      (define CURLOPT_SSL_CIPHER_LIST 10083)
      (define CURLOPT_HTTP_VERSION    84)
      (define CURLOPT_FTP_USE_EPSV    85)
      (define CURLOPT_SSLCERTTYPE 10086)
      (define CURLOPT_SSLKEY 10087)
      (define CURLOPT_SSLKEYTYPE 10088)
      (define CURLOPT_SSLENGINE 10089)
      (define CURLOPT_SSLENGINE_DEFAULT    90)
      (define CURLOPT_DNS_USE_GLOBAL_CACHE    91)
      (define CURLOPT_DNS_CACHE_TIMEOUT    92)
      (define CURLOPT_PREQUOTE 10093)
      (define CURLOPT_DEBUGFUNCTION 20094)
      (define CURLOPT_DEBUGDATA 10095)
      (define CURLOPT_COOKIESESSION    96)
      (define CURLOPT_CAPATH 10097)
      (define CURLOPT_BUFFERSIZE    98)
      (define CURLOPT_NOSIGNAL    99)

      (define CURLOPT_SHARE 10100)
      (define CURLOPT_PROXYTYPE    101)
      (define CURLOPT_ACCEPT_ENCODING 10102)
      (define CURLOPT_PRIVATE 10103)
      (define CURLOPT_HTTP200ALIASES 10104)
      (define CURLOPT_UNRESTRICTED_AUTH    105)
      (define CURLOPT_FTP_USE_EPRT    106)
      (define CURLOPT_HTTPAUTH    107)
      (define CURLOPT_SSL_CTX_FUNCTION 20108)
      (define CURLOPT_SSL_CTX_DATA 10109)
      (define CURLOPT_FTP_CREATE_MISSING_DIRS    110)
      (define CURLOPT_PROXYAUTH    111)
      (define CURLOPT_FTP_RESPONSE_TIMEOUT    112) (define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT)
      (define CURLOPT_IPRESOLVE    113)
      (define CURLOPT_MAXFILESIZE    114)
      (define CURLOPT_INFILESIZE_LARGE 30115)
      (define CURLOPT_RESUME_FROM_LARGE 30116)
      (define CURLOPT_MAXFILESIZE_LARGE 30117)
      (define CURLOPT_NETRC_FILE 10118)
      (define CURLOPT_USE_SSL    119)
      (define CURLOPT_POSTFIELDSIZE_LARGE 30120)
      (define CURLOPT_TCP_NODELAY    121)
      (define CURLOPT_FTPSSLAUTH    129)
      (define CURLOPT_IOCTLFUNCTION 20130)
      (define CURLOPT_IOCTLDATA 10131)
      (define CURLOPT_FTP_ACCOUNT 10134)
      (define CURLOPT_COOKIELIST 10135)
      (define CURLOPT_IGNORE_CONTENT_LENGTH    136)
      (define CURLOPT_FTP_SKIP_PASV_IP    137)
      (define CURLOPT_FTP_FILEMETHOD    138)
      (define CURLOPT_LOCALPORT    139)
      (define CURLOPT_LOCALPORTRANGE    140)
      (define CURLOPT_CONNECT_ONLY    141)
      (define CURLOPT_CONV_FROM_NETWORK_FUNCTION 20142)
      (define CURLOPT_CONV_TO_NETWORK_FUNCTION 20143)
      (define CURLOPT_CONV_FROM_UTF8_FUNCTION 20144)
      (define CURLOPT_MAX_SEND_SPEED_LARGE 30145)
      (define CURLOPT_MAX_RECV_SPEED_LARGE 30146)
      (define CURLOPT_FTP_ALTERNATIVE_TO_USER 10147)
      (define CURLOPT_SOCKOPTFUNCTION 20148)
      (define CURLOPT_SOCKOPTDATA 10149)
      (define CURLOPT_SSL_SESSIONID_CACHE    150)
      (define CURLOPT_SSH_AUTH_TYPES    151)
      (define CURLOPT_SSH_PUBLIC_KEYFILE 10152)
      (define CURLOPT_SSH_PRIVATE_KEYFILE 10153)
      (define CURLOPT_FTP_SSL_CCC    154)
      (define CURLOPT_TIMEOUT_MS    155)
      (define CURLOPT_CONNECTTIMEOUT_MS    156)
      (define CURLOPT_HTTP_TRANSFER_DECODING    157)
      (define CURLOPT_HTTP_CONTENT_DECODING    158)
      (define CURLOPT_NEW_FILE_PERMS    159)
      (define CURLOPT_NEW_DIRECTORY_PERMS    160)
      (define CURLOPT_POSTREDIR    161)
      (define CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 10162)
      (define CURLOPT_OPENSOCKETFUNCTION 20163)
      (define CURLOPT_OPENSOCKETDATA 10164)
      (define CURLOPT_COPYPOSTFIELDS 10165)
      (define CURLOPT_PROXY_TRANSFER_MODE    166)
      (define CURLOPT_SEEKFUNCTION 20167)
      (define CURLOPT_SEEKDATA 10168)
      (define CURLOPT_CRLFILE 10169)
      (define CURLOPT_ISSUERCERT 10170)
      (define CURLOPT_ADDRESS_SCOPE    171)
      (define CURLOPT_CERTINFO    172)
      (define CURLOPT_USERNAME 10173)
      (define CURLOPT_PASSWORD 10174)
      (define CURLOPT_PROXYUSERNAME 10175)
      (define CURLOPT_PROXYPASSWORD 10176)
      (define CURLOPT_NOPROXY 10177)
      (define CURLOPT_TFTP_BLKSIZE    178)
      (define CURLOPT_SOCKS5_GSSAPI_SERVICE 10179)
      (define CURLOPT_SOCKS5_GSSAPI_NEC    180)
      (define CURLOPT_PROTOCOLS    181)
      (define CURLOPT_REDIR_PROTOCOLS    182)
      (define CURLOPT_SSH_KNOWNHOSTS 10183)
      (define CURLOPT_SSH_KEYFUNCTION 20184)
      (define CURLOPT_SSH_KEYDATA 10185)
      (define CURLOPT_MAIL_FROM 10186)
      (define CURLOPT_MAIL_RCPT 10187)
      (define CURLOPT_FTP_USE_PRET    188)
      (define CURLOPT_RTSP_REQUEST    189)
      (define CURLOPT_RTSP_SESSION_ID 10190)
      (define CURLOPT_RTSP_STREAM_URI 10191)
      (define CURLOPT_RTSP_TRANSPORT 10192)
      (define CURLOPT_RTSP_CLIENT_CSEQ    193)
      (define CURLOPT_RTSP_SERVER_CSEQ    194)
      (define CURLOPT_INTERLEAVEDATA 10195)
      (define CURLOPT_INTERLEAVEFUNCTION 20196)
      (define CURLOPT_WILDCARDMATCH    197)
      (define CURLOPT_CHUNK_BGN_FUNCTION 20198)
      (define CURLOPT_CHUNK_END_FUNCTION 20199)
      (define CURLOPT_FNMATCH_FUNCTION 20200)
      (define CURLOPT_CHUNK_DATA 10201)
      (define CURLOPT_FNMATCH_DATA 10202)
      (define CURLOPT_RESOLVE 10203)
      (define CURLOPT_TLSAUTH_USERNAME 10204)
      (define CURLOPT_TLSAUTH_PASSWORD 10205)
      (define CURLOPT_TLSAUTH_TYPE 10206)
      (define CURLOPT_TRANSFER_ENCODING    207)
      (define CURLOPT_CLOSESOCKETFUNCTION 20208)
      (define CURLOPT_CLOSESOCKETDATA 10209)
      (define CURLOPT_GSSAPI_DELEGATION    210)
      (define CURLOPT_DNS_SERVERS 10211)
      (define CURLOPT_ACCEPTTIMEOUT_MS    212)
      (define CURLOPT_TCP_KEEPALIVE    213)
      (define CURLOPT_TCP_KEEPIDLE    214)
      (define CURLOPT_TCP_KEEPINTVL    215)
      (define CURLOPT_SSL_OPTIONS    216)
      (define CURLOPT_MAIL_AUTH 10217)
      (define CURLOPT_SASL_IR    218)
      (define CURLOPT_XFERINFOFUNCTION 20219)
      (define CURLOPT_XOAUTH2_BEARER 10220)
      (define CURLOPT_DNS_INTERFACE 10221)
      (define CURLOPT_DNS_LOCAL_IP4 10222)
      (define CURLOPT_DNS_LOCAL_IP6 10223)
      (define CURLOPT_LOGIN_OPTIONS 10224)
      (define CURLOPT_SSL_ENABLE_NPN    225)
      (define CURLOPT_SSL_ENABLE_ALPN    226)
      (define CURLOPT_EXPECT_100_TIMEOUT_MS    227)
      (define CURLOPT_PROXYHEADER 10228)
      (define CURLOPT_HEADEROPT    229)
      (define CURLOPT_PINNEDPUBLICKEY 10230)
      (define CURLOPT_UNIX_SOCKET_PATH 10231)
      (define CURLOPT_SSL_VERIFYSTATUS    232)
      (define CURLOPT_SSL_FALSESTART    233)
      (define CURLOPT_PATH_AS_IS    234)
      (define CURLOPT_PROXY_SERVICE_NAME 10235)
      (define CURLOPT_SERVICE_NAME 10236)
      (define CURLOPT_PIPEWAIT    237)
      (define CURLOPT_DEFAULT_PROTOCOL 10238)
      (define CURLOPT_STREAM_WEIGHT    239)
      (define CURLOPT_STREAM_DEPENDS 10240)
      (define CURLOPT_STREAM_DEPENDS_E 10241)
      (define CURLOPT_TFTP_NO_OPTIONS    242)
      (define CURLOPT_CONNECT_TO 10243)
      (define CURLOPT_TCP_FASTOPEN    244)
      (define CURLOPT_KEEP_SENDING_ON_ERROR    245)
      (define CURLOPT_PROXY_CAINFO 10246)
      (define CURLOPT_PROXY_CAPATH 10247)
      (define CURLOPT_PROXY_SSL_VERIFYPEER    248)
      (define CURLOPT_PROXY_SSL_VERIFYHOST    249)
      (define CURLOPT_PROXY_SSLVERSION    250)
      (define CURLOPT_PROXY_TLSAUTH_USERNAME 10251)
      (define CURLOPT_PROXY_TLSAUTH_PASSWORD 10252)
      (define CURLOPT_PROXY_TLSAUTH_TYPE 10253)
      (define CURLOPT_PROXY_SSLCERT 10254)
      (define CURLOPT_PROXY_SSLCERTTYPE 10255)
      (define CURLOPT_PROXY_SSLKEY 10256)
      (define CURLOPT_PROXY_SSLKEYTYPE 10257)
      (define CURLOPT_PROXY_KEYPASSWD 10258)
      (define CURLOPT_PROXY_SSL_CIPHER_LIST 10259)
      (define CURLOPT_PROXY_CRLFILE 10260)
      (define CURLOPT_PROXY_SSL_OPTIONS    261)
      (define CURLOPT_PRE_PROXY 10262)
      (define CURLOPT_PROXY_PINNEDPUBLICKEY 10263)
      (define CURLOPT_ABSTRACT_UNIX_SOCKET 10264)
      (define CURLOPT_SUPPRESS_CONNECT_HEADERS    265)
      (define CURLOPT_REQUEST_TARGET 10266)
      (define CURLOPT_SOCKS5_AUTH    267)
      (define CURLOPT_SSH_COMPRESSION    268)
      (define CURLOPT_MIMEPOST 10269)
      (define CURLOPT_TIMEVALUE_LARGE 30270)
      (define CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS    271)
      (define CURLOPT_RESOLVER_START_FUNCTION 20272)
      (define CURLOPT_RESOLVER_START_DATA 10273)
      (define CURLOPT_HAPROXYPROTOCOL    274)
      (define CURLOPT_DNS_SHUFFLE_ADDRESSES    275)
      (define CURLOPT_TLS13_CIPHERS 10276)
      (define CURLOPT_PROXY_TLS13_CIPHERS 10277)
      (define CURLOPT_DISALLOW_USERNAME_IN_URL    278)
      (define CURLOPT_DOH_URL 10279)
      (define CURLOPT_UPLOAD_BUFFERSIZE    280)
      (define CURLOPT_UPKEEP_INTERVAL_MS    281)
      (define CURLOPT_CURLU 10282)
      (define CURLOPT_TRAILERFUNCTION 20283)
      (define CURLOPT_TRAILERDATA 10284)
      (define CURLOPT_HTTP09_ALLOWED    285)
      (define CURLOPT_ALTSVC_CTRL    286)
      (define CURLOPT_ALTSVC 10287)
      (define CURLOPT_MAXAGE_CONN    288)
      (define CURLOPT_SASL_AUTHZID 10289)
      ; not define for CURLOPT_LASTENTRY

   (define curl_easy_init (libcurl CURL* "curl_easy_init"))
   (define curl_easy_setopt (libcurl CURLcode "curl_easy_setopt" CURL* CURLoption fft-any))
   (define curl_easy_reset (libcurl CURLcode "curl_easy_reset" CURL*))

   (define curl_easy_perform (libcurl fft-void "curl_easy_perform" type-vptr))
   (define curl_easy_cleanup (libcurl fft-void "curl_easy_cleanup" type-vptr))

   (define curl_global_init (libcurl CURLcode "curl_global_init" fft-long))
      (define CURL_GLOBAL_SSL   (<< 1 0))
      (define CURL_GLOBAL_WIN32 (<< 1 1))
      (define CURL_GLOBAL_ALL (bor CURL_GLOBAL_SSL CURL_GLOBAL_WIN32))
      (define CURL_GLOBAL_NOTHING 0)
      (define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL)
      (define CURL_GLOBAL_ACK_EINTR (<< 1 2))

   ; --------------------------------------------------------------------------------------------
   ; highlevel api:
   (curl_global_init CURL_GLOBAL_ALL)
   (define curl_easy_setopt_l (libcurl CURLcode "curl_easy_setopt" CURL* CURLoption fft-long))
   (define curl_easy_setopt_s (libcurl CURLcode "curl_easy_setopt" CURL* CURLoption type-string))
   (define curl_easy_setopt_c (libcurl CURLcode "curl_easy_setopt" CURL* CURLoption type-callable))

   (define opts {
      'url           (list CURLOPT_URL curl_easy_setopt_s)
      'writefunction (list CURLOPT_WRITEFUNCTION curl_easy_setopt_c)
   })

   (define (make-curl)
      (define curl (curl_easy_init))
      (case-lambda
         ; set option
         ((opt value)
            (apply (lambda (opt setopt)
               (setopt curl opt value)) (opts opt (list opt curl_easy_setopt))))
         ((action)
            (case action
               ('perform
                  (curl_easy_perform curl))
               ('cleanup
                  (curl_easy_cleanup curl))

               ('reset
                  (curl_easy_reset curl))
               (else
                  (print "lib curl: unknown " action " action"))))
         ; no option - perform an default action
         (()
            (curl_easy_perform curl))))

   ;; example:
   ; (define curl (make-curl))
   ; (curl 'url "https://example.com")
   ; (curl 'perform) ;; or just (curl)
))
