# Nim CLI Wrapper for the ESV API
# © 2023 Jonathan Bernard

## Simple command-line wrapper around the ESV API.

import std/[httpclient, json, logging, os, re, strutils, uri]
import cliutils, docopt, zero_functional

when isMainModule:
  const USAGE = """Usage:
  esv_api <reference> [options]

Options:

  --debug                       Log debug information.

  --echo-args                   Echo back the arguments that were passed on the
                                command line for debugging purposes.

  -t, --esv-api-token <token>   Provide the API token on the command line. By
                                default this will be read either from the
                                .esv_api.cfg.json file or the ESV_API_TOKEN
                                envionment variable.
"""

  let consoleLogger = newConsoleLogger(
    levelThreshold=lvlInfo,
    fmtStr="esv_api - $levelname: ")
  logging.addHandler(consoleLogger)

  try:
    # Parse arguments
    let args = docopt(USAGE, version = "0.1.0")

    if args["--debug"]:
      consoleLogger.levelThreshold = lvlDebug

    if args["--echo-args"]: stderr.writeLine($args)

    let cfgFilePath = getEnv("HOME") / ".esv_api.cfg.json"
    var cfgFileJson = newJObject()
    if fileExists(cfgFilePath):
      debug "Loading config from " & cfgFilePath
      cfgFileJson = parseFile(cfgFilePath)

    let cfg = CombinedConfig(docopt: args, json: cfgFileJson)
    let apiToken = cfg.getVal("esv-api-token")
    let apiRoot = cfg.getVal("esv-api-root", "https://api.esv.org")
    let reference = $args["<reference>"]

    let http = newHttpClient()
    http.headers = newHttpHeaders({"Authorization": "Token " & apiToken})

    let urlPath = apiRoot & "/v3/passage/text/?q=" & encodeUrl(reference)
    debug "requesting " & urlPath
    let respJson = parseJson(http.getContent(urlPath))

    let formattedPassages = respJson["passages"].getElems -->
      map(it.getStr.multiReplace([(re"\[(\d+)\]", "$1")]))

    echo formattedPassages.join("\p")

  except CatchableError:
    fatal getCurrentExceptionMsg()
    debug getCurrentException().getStackTrace()
    quit(QuitFailure)