#' Validate provided aligner
#'
#' Only "biscuit", "bismark", and "bsbolt" are currently supported
#' @param aligner The input alinger
#' @returns true; quits if the input is not among supported_aligners
#'
#' @keywords internal
verify_aligner_or_stop <- function(aligner) {
  supported_aligners <- c("biscuit", "bismark", "bsbolt")
  if (!(aligner %in% supported_aligners)) {
    stop(paste(
      "aligner =",
      aligner,
      "not supported. Use one of the supported aligners:",
      paste(supported_aligners, collapse = ", ")
    ))
  }
}

#' GRanges to region strings
#'
#' Coerces GenomicRanges to `chr:start-end` strings with `as.character`. If any
#' regions have the same start and end, `as.character` returns `chr:start`
#' strings which are invalid for the htslib API. These are corrected to
#' `chr:start-start`.
#'
#' @param gr A GRanges object
#' @returns A character vector
#'
#' @export
#' @examples
#' if (requireNamespace("GenomicRanges", quietly = TRUE)) {
#'   get_granges_string(GenomicRanges::GRanges(c("chr1:1-10", "chr2:15-20")))
#' }
get_granges_string <- function(gr) {
  if (!requireNamespace("GenomicRanges", quietly = TRUE)) {
    stop("The 'GenomicRanges' package must be installed for this functionality")
  }
  region_str <- as.character(gr)
  singles <- which(GenomicRanges::width(gr) == 1)
  single_count <- length(singles)
  if (single_count > 0) {
    region_str[singles] <- gsub(":([0-9]+)", ":\\1-\\1", region_str[singles])
    message("Corrected ", single_count, " invalid 'chr:start' region strings to 'chr:start-start'")
  }

  names(region_str) <- names(gr)
  region_str
}

#' DataFrame to region strings
#'
#' Convert DataFrame to a vector of strings. Set feature names in a "name" column
#'
#' @param regions_df A data frame with "chr", "start" and "end" columns
#' @param feature_col The data frame column to use as the names of the output string vector
#'
#' @importFrom data.table setDT
#'
#' @returns A character vector
#'
#' @export
#' @examples
#' (df <- data.frame(chr = c("chr1", "chr2"), start = c(1, 5), end = c(4, 10)))
#' get_df_string(df)
get_df_string <- function(regions_df, feature_col = NULL) {
  colnames.check <- colnames(regions_df)[seq_len(3)]
  stopifnot(
    "colnames must be 'chr', 'start' and 'end'" = colnames.check == c("chr", "start", "end")
  )
  chr <- start <- end <- NULL
  regions.dt <- setDT(regions_df)
  regions <- regions.dt[, paste0(chr, ":", start, "-", end)]
  if (!is.null(feature_col) && feature_col %in% colnames(regions_df)) {
    names(regions) <- regions_df[[feature_col]]
  }
  return(regions)
}

get_df_from_string <- function(regions) {
  start <- NULL
  as.data.table(regions)[, tstrsplit(regions, ":|-", fixed = FALSE, names = c("chr", "start", "end"))][,
    start := as.integer(start)
  ]
}

# Get GRanges from chr and pos vector
getGR <- function(chr, pos) {
  if (requireNamespace("GenomicRanges", quietly = TRUE)) {
    GenomicRanges::GRanges(chr, IRanges::IRanges(pos, pos, width = 1))
  }
}

# Check if package is loaded
# https://github.com/HenrikBengtsson/R.utils/blob/74def095eaa244e355d05fdf790ee6393dad1d99/R/isPackageLoaded.R#L33-L43
is_package_loaded <- function(package, caller, fail) {
  loaded_packages <- gsub("package:", "", search())
  if (package %in% loaded_packages) {
    return(TRUE)
  }
  if (fail) {
    msg <- sprintf("Please load the '%s' package to use '%s' output", package, caller)
    stop(msg)
  }
  FALSE
}
