# WARNING - Generated by {fusen} from dev/flat_chars_structure_general.Rmd: do not edit by hand

#' Generalized characters structure
#'
#' Get any user-defined patterns from each symbol of character vector
#' @param input_vector Character. Vector to process
#' @param split Character 1L. Symbol separator
#' @param patterns_and_replacements Character. Named character vector of patterns (names) and replacements (values)
#' @param unique Logical 1L. If TRUE, the result is reduced to unique values
#' @param named_output Logical 1L. If TRUE, output vector is named after corresponding input values. 
#' @return A character vector describing the generalized structure of each
#'   element of \code{input_vector}. If \code{named_output} is \code{TRUE},
#'   the vector is named after the corresponding input values. If
#'   \code{unique} is \code{TRUE}, only structures for unique input values
#'   are returned; otherwise one structure per element of \code{input_vector}.
#' @export
#' @examples
#'
#' input <- c("ABC123", "DE4F56", "789GHI", "ABC123")
#'
#' # Default values of unique and named_output:
#' chars_structure_general(input_vector = input, split = "", 
#'                         patterns_and_replacements = c("[:alpha:]" = "[letter]", 
#'                                                       "[:digit:]" = "[number]"), 
#'                         unique = TRUE, named_output = TRUE)
#'
#' # unique is set to default value TRUE and named_output is set to FALSE:
#' chars_structure_general(input_vector = input, split = "", 
#'                         patterns_and_replacements = c("[:alpha:]" = "[letter]", 
#'                                                       "[:digit:]" = "[number]"), 
#'                         unique = TRUE, named_output = FALSE)
#'
#' # unique is set to FALSE and named_output to FALSE:
#' chars_structure_general(input_vector = input, split = "", 
#'                         patterns_and_replacements = c("[:alpha:]" = "[letter]", 
#'                                                       "[:digit:]" = "[number]"), 
#'                         unique = FALSE, named_output = FALSE)
#'
#' # unique is set to FALSE and named_output to defalut value TRUE:
#' chars_structure_general(input_vector = input, split = "", 
#'                         patterns_and_replacements = c("[:alpha:]" = "[letter]", 
#'                                                       "[:digit:]" = "[number]"), 
#'                         unique = FALSE, named_output = TRUE)
chars_structure_general <- function (input_vector, 
                 split = "", 
                 patterns_and_replacements, unique = TRUE, named_output = TRUE) {
  
  if (isFALSE(is.character(input_vector))) {
    
    stop("input_vector must be a character vector")
  }
  
  iunique <- unique(input_vector)
  result <- strsplit(iunique, split)
  result <- lapply(
    result, 
    \(x) {
      stringr::str_replace_all(x, patterns_and_replacements)})
  result <- lapply(result, rle)
  result <- lapply(
    result, 
    \(x) {
      paste(paste0(x$lengths, x$values), collapse = ", ")
    })
  result <- unlist(result)
  result_d <- data.frame(input_unique = iunique, chars_structure = result)
  
  if (unique) {
    if (named_output) {
      stats::setNames(result, iunique)
    } else {result}
  } else {
    ljoin_result <- dplyr::left_join(
      data.frame(input_vector = input_vector), 
      result_d, by = c(input_vector = "input_unique"))
    
    if (named_output) {
      stats::setNames(ljoin_result[["chars_structure"]], 
                      ljoin_result[["input_vector"]])
    } else {ljoin_result[["chars_structure"]]}
  }
}
