#' Filter Data List Column
#'
#' @description Create a column filter for a \pkg{reactable} table that pairs a text
#'   input with an HTML `datalist`, giving users autocomplete suggestions drawn from
#'   the column's unique values.
#'   Requires that the \pkg{htmltools} package is available.
#'
#' @details The returned function is intended for use as a column's `filterInput` in
#'   [reactable::colDef()]. When rendered, it produces a text box backed by a
#'   `datalist` of the sorted unique values in that column; typing filters the table
#'   via `Reactable.setFilter()`, while the suggestions assist exact matches.
#'
#' @param table_id 'character' string.
#'   Unique identifier of the table the filter belongs to. Must match the `elementId`
#'   given to the table so that `Reactable.setFilter()` can target it.
#'
#' @param style 'character' string.
#'   CSS applied to the text input element. Defaults to a full-width, 28px-tall box.
#'
#' @return Returns a function of two arguments, `values` (the column's values) and
#'   `name` (the column name), which returns an \pkg{htmltools} tag list for the
#'   filter input.
#'
#' @author J.C. Fisher, U.S. Geological Survey, Idaho Water Science Center
#'
#' @keywords internal
#' @export
#'
#' @keywords internal
#'
#' @references Adapted from the \pkg{reactable} "Custom Filtering" vignette
#'   (\url{https://github.com/glin/reactable/blob/HEAD/vignettes/custom-filtering.Rmd}),
#'   by Greg Lin and Tanner Linsley, 2019 (MIT License). Accessed 2024-05-30.
#'
#' @examples
#' f <- filter_data_list("table-id")

filter_data_list <- function(
  table_id,
  style = "width: 100%; height: 28px;"
) {
  # check system dependencies
  if (!requireNamespace("htmltools", quietly = TRUE)) {
    stop("Creating a data list column filter requires the 'htmltools' package", call. = FALSE)
  }

  # check arguments
  checkmate::assert_string(table_id, min.chars = 1)
  checkmate::assert_string(style)

  # return the filter-input function used by reactable::colDef(filterInput = ...)
  function(values, name) {
    list_id <- sprintf("%s-%s-list", table_id, name)
    htmltools::tagList(
      htmltools::tags$input(
        type = "text",
        list = list_id,
        oninput = sprintf(
          "Reactable.setFilter('%s', '%s', event.target.value || undefined)",
          table_id,
          name
        ),
        "aria-label" = sprintf("Filter %s", name),
        style = style
      ),
      htmltools::tags$datalist(
        id = list_id,
        lapply(
          sort(unique(values)),
          FUN = function(x) htmltools::tags$option(value = x)
        )
      )
    )
  }
}
