#' return a SQLite connection (read only) to an INCAtools Semantic SQL ontology
#' @import BiocFileCache
#' @import RSQLite
#' @importFrom R.utils gunzip
#' @import DBI
#' @importFrom utils download.file
#' @param ontology character(1) short string prefixing .db.gz in the INCAtools collection
#' @param cache a BiocFileCache instance, defaulting to BiocFileCache::BiocFileCache()
#' @param cacheid character(1) or NULL; if non-null, the associated SQLite resource will be used from cache
#' @param \dots passed to download.file
#' @return an RSQLite DBI connection instance
#' @note When the cache is searched, the string given as 'ontology' will be prefixed with '^'.  This
#' helps avoid confusion between pcl.db and cl.db, for example.
#' @examples
#' # first time will involve a download and decompression
#' aionto <- retrieve_semsql_conn("aio")
#' head(DBI::dbListTables(aionto))
#' dplyr::tbl(aionto, "class_node") |> head()
#' @export
retrieve_semsql_conn <- function(ontology = "efo",
                                 cache = BiocFileCache::BiocFileCache(), cacheid = NULL, ...) {
  #
  # this function checks for cached version of ontology database
  # and if present, returns SQLite connection to it.  otherwise
  # it caches and then recurses
  #
  if (!is.null(cacheid)) {
    cached_path <- bfcinfo(cache, cacheid)$rpath
    return(dbConnect(SQLite(), cached_path, SQLITE_RO))
  }
  rname <- paste0(ontology, "_bbop_ontoproc2")
  bbop_info <- BiocFileCache::bfcquery(cache, rname)
  ind <- which(startsWith(bbop_info$rname, rname))
  if (length(ind) > 0) {
    if (length(ind) > 1) {
      message(
        sprintf("multiple cache entries found matching request %s", rname),
        "please be more specific, by supplying cache id as 'BFCnnn'.",
        sprintf("see %s in cache\n", paste(bbop_info$rid, collapse = ", "))
      )
      stop("cannot proceed with ambiguous ontology spec")
    }
    cached_path <- bbop_info[ind, "rpath"]$rpath # ind is length 1
    return(dbConnect(SQLite(), cached_path, SQLITE_RO))
  } else {
    addr <- semsql_url(ontology)
    zdbname <- basename(addr)
    dbname <- sub(".gz$", "", zdbname)
    td <- tempfile()
    dir.create(td)
    on.exit(unlink(td, recursive = TRUE))
    ztmploc <- file.path(td, zdbname)
    tmploc <- file.path(td, dbname)
    download.file(addr, file.path(td, zdbname), headers = c("User-Agent" = "ontoProc2"), ...)
    gunzip(ztmploc) # file now at tmploc
    addv <- BiocFileCache::bfcadd(cache,
      rname = rname,
      rtype = "local", fpath = tmploc, action = "copy"
    )
    id <- bfcquery(cache, basename(addv))$rid
    if (!isTRUE(startsWith(id, "BFC"))) stop("cache action failed") # avoid possibly infinite Recall
    Recall(ontology = ontology, cache = cache, cacheid = id)
  }
}
