# Statistics of the World -- official R client (single file).
# Requires: jsonlite (install.packages("jsonlite")).
#
#   source("sotw.R")
#   sotw <- SOTW()                      # anonymous / free tier
#   sotw <- SOTW(api_key = "YOUR_KEY")  # higher limits
#
#   sotw$indicators(category = "Economy")
#   sotw$country("USA")
#   sotw$history("NY.GDP.MKTP.CD", "USA")
#   sotw$rankings("NY.GDP.MKTP.CD")
#   sotw$series_observations("UST.YC.10Y")
#   sotw$calendar(institution = "BLS")
#
# Data sourced from primary institutions under each source's licence. MIT licensed.
# Docs: https://statisticsoftheworld.com/api-docs

SOTW <- function(api_key = NULL, base_url = "https://statisticsoftheworld.com", timeout = 30) {
  if (!requireNamespace("jsonlite", quietly = TRUE)) stop("Please install.packages('jsonlite')")
  base_url <- sub("/+$", "", base_url)

  get <- function(path, params = list()) {
    params <- params[!vapply(params, is.null, logical(1))]
    qs <- ""
    if (length(params) > 0) {
      pairs <- vapply(names(params), function(k)
        paste0(utils::URLencode(k, TRUE), "=", utils::URLencode(as.character(params[[k]]), TRUE)),
        character(1))
      qs <- paste0("?", paste(pairs, collapse = "&"))
    }
    url <- paste0(base_url, "/api/v1/", sub("^/", "", path), qs)
    h <- c("User-Agent" = "sotw-r/1.0.0")
    if (!is.null(api_key)) h["X-API-Key"] <- api_key
    con <- url(url, headers = h)
    on.exit(try(close(con), silent = TRUE))
    jsonlite::fromJSON(paste(readLines(con, warn = FALSE), collapse = ""))
  }

  enc <- function(x) utils::URLencode(x, reserved = TRUE)

  list(
    indicators = function(category = NULL, limit = NULL, offset = NULL)
      get("indicators", list(category = category, limit = limit, offset = offset)),
    indicator = function(id) get(paste0("indicators/", enc(id))),
    countries = function() get("countries"),
    country = function(id) get(paste0("countries/", enc(id))),
    history = function(indicator, country) get(paste0("history/", enc(indicator), "/", enc(country))),
    rankings = function(indicator) get(paste0("rankings/", enc(indicator))),
    compare = function(countries, indicators)
      get("compare", list(countries = paste(countries, collapse = ","),
                          indicators = paste(indicators, collapse = ","))),
    series = function() get("series"),
    series_observations = function(id, geo = NULL, start = NULL, end = NULL, limit = NULL)
      get(paste0("series/", enc(id)), list(geo = geo, start = start, end = end, limit = limit)),
    search = function(q) get("search", list(q = q)),
    calendar = function(institution = NULL, country = NULL, from = NULL, to = NULL)
      get("calendar", list(institution = institution, country = country, from = from, to = to))
  )
}
