---
title: "Custom basic_table arguments module"
author: "Maciej NasiƄski"
output: rmarkdown::html_vignette
runtime: shiny
vignette: >
  %\VignetteIndexEntry{Custom basic_table arguments module}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

This vignette will guide you through implementation of custom `rtables::basic_table` arguments for `rtables` tables 
based modules. We will enable 2 ways of updating `rtables::basic_table` by the end users.
The `rtables::basic_table` specification could be updated with the `teal.basic_table_args` `options` variable or a 
`ggplot2_args` argument in a `tm_g_*` module. We still take into account default specification set up by the module 
creator in the server function, which has the lowest priority.

The implementation should consist of 5 steps:

1. Add the `basic_table_args` arguments to the `tm_t_*` function and then its server function.
The default should be set to
the `basic_table_args()` function for a single plot.
and  `list(default = basic_table_args())` multi-table modules.
2. Add validation (e.g. `stopifnot` or `checkmate`) for the `basic_table_args` arguments to the `tm_*` function.
The validation is more complex for multi-table modules, where the `ggplot2_args` could be a `list`.
The module creator has to provide a list of plots names, which should be validated at this step and added to the `param` 
field in `roxygen2`. For multi-table modules the step 
`if (is_basic_table_args) basic_table_args <- list(default = basic_table_args)` is recommended.
3. Aggregate and reduce all `basic_table_args` sources with `resolve_basic_table_args()`.
4. Use the `parse_basic_table_args()` function which will aggregate and reduce all inputs
to one expression.
5. Add the created expression to the chunk with a table.

The `parse_basic_table_args()` function picks the first non NULL value for each argument, checking in order:

1. `basic_table_args` arguments provided by the end user.
For multi-table case, per table (`basic_table_args_table`) and then default (`basic_table_args_default`) setup.
2. Global R variable (`options`), `teal.basic_table_args`.
3. `basic_table_args_developer` which is a developer setup, lowest priority.

## Example - Single-Table Module

```{r warning=FALSE}
library(shiny)
library(teal.widgets)
library(magrittr)

options("teal.basic_table_args" = basic_table_args(title = "ENV_TITLE"))

basic_table_args <- list(
  default = basic_table_args(prov_footer = "USER_FOOTER"),
  table1 = basic_table_args(subtitles = "USER_SUBTITLES_TABLE1"),
  table2 = basic_table_args(subtitles = "USER_SUBTITLES_TABLE2")
)


ui <- fluidPage(
  shinyjs::useShinyjs(),
  tags$div(verbatimTextOutput("table1"))
)

server <- function(input, output, session) {
  dev_table_args <- basic_table_args(show_colcounts = TRUE)

  table_expr <- substitute(
    expr = {
      tt <- f_table_expr %>%
        rtables::split_cols_by("Species") %>%
        rtables::analyze(vars = "Sepal.Length", afun = function(x) {
          rtables::in_rows(
            "Mean" = rtables::rcell(mean(x), format = "xx.xx"),
            "Range" = rtables::rcell(range(x), format = "xx.xx - xx.xx")
          )
        })
      table2 <- rtables::build_table(tt, iris)
      table2
    },
    env = list(f_table_expr = parse_basic_table_args(
      resolve_basic_table_args(
        user_table = basic_table_args$table2,
        user_default = basic_table_args$default,
        module_table = dev_table_args
      )
    ))
  )
  output$table1 <- renderPrint(eval(table_expr))
}

if (interactive()) {
  shinyApp(ui, server)
}
```