#!/usr/bin/env guile3.0
!#

(use-modules (web client)
             (json)
             (rnrs bytevectors)
             (ice-9 receive))

(define api-key "99631af2d6db903d1f689c7d2cb13764")
(define city-id "5809844")
(define units "metric")

;; Construct the openweathermap URL with API token, city ID, and unit of measurement
(define weather-url
  (format #f "http://api.openweathermap.org/data/2.5/weather?id=~a&units=~a&appid=~a"
          city-id units api-key))

;; Define weather icons as an association list
(define weather-icons
  '(("clear sky" . "☀️")
    ("few clouds" . "🌤️")
    ("scattered clouds" . "🌥️")
    ("broken clouds" . "☁️")
    ("overcast clouds" . "☁️")
    ("shower rain" . "🌦️")
    ("light rain" . "🌧️")
    ("light intensity drizzle" . "🌧️")
    ("rain" . "🌧️")
    ("moderate rain" . "🌧️")
    ("thunderstorm" . "⛈️")
    ("snow" . "❄️")
    ("mist" . "🌫️")
    ("haze" . "🌫️")
    ("smoke" . "🌫️")
    ("fog" . "🌫️")))

;; Convert Celsius to Fahrenheit
(define (celsius-to-fahrenheit celsius)
  (+ (* celsius (/ 9 5)) 32))

;; Get weather icon based on description
(define (get-weather-icon description)
  (or (assoc-ref weather-icons description) "❓"))

;; Parse and extract weather data from JSON
(define (extract-weather-data json-data)
  (let* ((main (assoc "main" json-data))
         (temp-c (and main
                      (cdr (assoc "temp" (cdr main)))))

         ;; Round and convert to exact integer
         (temp-c-value (and temp-c
                            (inexact->exact
                             (round temp-c))))
         (weather-description
          (cdr (assoc "description"
                      (vector-ref (cdr (assoc "weather" json-data)) 0)))))

    ;; Return temperature (C, F), description, and icon
    (values temp-c-value
            (and temp-c-value
                 (inexact->exact
                  (round (celsius-to-fahrenheit temp-c-value))))
            weather-description
            (get-weather-icon weather-description))))

;; Fetch and display weather data
(define (get-weather)
  ;; Request and parse the data
  (receive (response-status response-body)
      (http-request weather-url)
    (let ((json-data (json-string->scm
                      (utf8->string response-body))))
      (call-with-values
          (lambda () (extract-weather-data json-data))
        (lambda (temp-c temp-f description icon)
          ;; For debugging
          ;;(format #t "Description: ~a ~%" description)

          ;; Display the weather information
          (if temp-c
              (format #t "~a ~d°C / ~d°F~%"
                      icon temp-c temp-f)
              (display "Error: Temperature data not available.\n")))))))

(get-weather)
