# Documentation methods for the slabinterval family
#
# Author: mjskay
###############################################################################



# slabinterval shortcut stats/geoms ---------------------------------------------------

rd_slabinterval_shortcut_geom = function(
  geom_name, chart_type
) {
  geom = get(paste0("Geom", camel_case(geom_name)))

  default_aes = lapply(geom$default_computed_aes, function(x) deparse0(get_expr(x)))
  default_aes = if (length(default_aes)) paste(names(default_aes), "=", default_aes, collapse = ", ")
  default_aes = gsub("fct_rev_", "forcats::fct_rev", default_aes, fixed = TRUE)

  c(
    glue_doc('@title <<title_case(chart_type)>> plot (shortcut geom)'),
    glue_doc('
      @description
      Shortcut version of [geom_slabinterval()] for creating <<chart_type>> plots.

      **Roughly equivalent to:**
      '),
    rd_shortcut_geom(geom_name),
    if (length(default_aes)) glue_doc('
      @details
      This geom wraps [geom_slabinterval()] with defaults designed to produce
      <<chart_type>> plots. Default aesthetic mappings are applied if the `.width` column
      is present in the input data (e.g., as generated by the [point_interval()] family of functions),
      making this geom often more convenient than vanilla [ggplot2][ggplot2::ggplot2] geometries when used with
      functions like [median_qi()], [mean_qi()], [mode_hdi()], etc.

      Specifically, if `.width` is present in the input, [geom_<<geom_name>>()] acts
      as if its default aesthetics are `aes(<<default_aes>>)`
      '),
    '@inheritParams geom_slabinterval',
    rd_layer_params(geom_name, as_dots = FALSE),
    glue_doc('
      @return A [ggplot2::Geom] representing a <<chart_type>> geometry which can
      be added to a [`ggplot()`][ggplot2::ggplot] object.'),
    rd_slabinterval_aesthetics(geom_name),
    glue_doc('
      @seealso
      See [stat_<<geom_name>>()] for the stat version, intended for
      use on sample data or analytical distributions.
      See [geom_slabinterval()] for the geometry this shortcut is based on.
      '),
    '@family slabinterval geoms'
  )
}

rd_slabinterval_shortcut_stat = function(
  stat_name, chart_type,
  geom_name = stat_name,
  example_layers = NULL,
  describe = TRUE
) {
  stat = get(paste0("Stat", camel_case(stat_name)))
  geom = get(paste0("Geom", camel_case(geom_name)))

  example_layers = if (length(example_layers) > 0) {
    paste0(" +\n  ", example_layers, collapse = "")
  } else {
    ""
  }

  c(
    glue_doc('@title <<title_case(chart_type)>> plot (shortcut stat)'),
    if (describe) glue_doc('
      @description
      Shortcut version of [stat_slabinterval()] with [geom_<<geom_name>>()] for
      creating <<chart_type>> plots.

      **Roughly equivalent to:**
      '),
    if (describe) rd_shortcut_stat(stat_name, geom_name),
    '@inheritParams stat_slabinterval',
    '@inheritParams geom_slabinterval',
    rd_layer_params(geom_name, stat, as_dots = TRUE),
    glue_doc('
      @param geom <[Geom][ggplot2::Geom] | [string][character]> Use to override
      the default connection between [stat_<<stat_name>>()] and [geom_<<geom_name>>()]'),
    '@template details-x-y-xdist-ydist',
    glue_doc('
      @return A [ggplot2::Stat] representing a <<chart_type>> geometry which can
      be added to a [`ggplot()`][ggplot2::ggplot] object.'),
    rd_slabinterval_computed_variables(stat),
    rd_slabinterval_aesthetics(geom_name, stat),
    glue_doc('
      @seealso
      See [geom_<<geom_name>>()] for the geom underlying this stat.
      See [stat_slabinterval()] for the stat this shortcut is based on.
      '),
    '@family slabinterval stats',
    glue_doc('
      @examples
      library(dplyr)
      library(ggplot2)
      library(distributional)

      theme_set(theme_ggdist())

      # ON SAMPLE DATA
      set.seed(1234)
      df = data.frame(
        group = c("a", "b", "c"),
        value = rnorm(1500, mean = c(5, 7, 9), sd = c(1, 1.5, 1))
      )
      df %>%
        ggplot(aes(x = value, y = group)) +
        stat_<<stat_name>>()<<example_layers>>

      # ON ANALYTICAL DISTRIBUTIONS
      dist_df = data.frame(
        group = c("a", "b", "c"),
        mean =  c(  5,   7,   8),
        sd =    c(  1, 1.5,   1)
      )
      # Vectorized distribution types, like distributional::dist_normal()
      # and posterior::rvar(), can be used with the `xdist` / `ydist` aesthetics
      dist_df %>%
        ggplot(aes(y = group, xdist = dist_normal(mean, sd))) +
        stat_<<stat_name>>()<<example_layers>>
      ')
  )
}


# computed variables ------------------------------------------------------

rd_slabinterval_computed_variables = function(stat = StatSlabinterval) {
  out = glue_doc('
      @section Computed Variables:
      The following variables are computed by this stat and made available for
      use in aesthetic specifications ([`aes()`][ggplot2::aes]) using the [`after_stat()`][ggplot2::after_stat]
      function or the `after_stat` argument of [`stage()`][ggplot2::stage]:

      - `x` or `y`: For slabs, the input values to the slab function.
        For intervals, the point summary from the interval function. Whether it is `x` or `y` depends on `orientation`
      - `xmin` or `ymin`: For intervals, the lower end of the interval from the interval function.
      - `xmax` or `ymax`: For intervals, the upper end of the interval from the interval function.
      - `.width`: For intervals, the interval width as a numeric value in `[0, 1]`.
        For slabs, the width of the smallest interval containing that value of the slab.
      - `level`: For intervals, the interval width as an ordered factor.
        For slabs, the level of the smallest interval containing that value of the slab.
      - `pdf`: For slabs, the probability density function (PDF).
        If `options("ggdist.experimental.slab_data_in_intervals")` is `TRUE`:
        For intervals, the PDF at the point summary; intervals also have `pdf_min` and `pdf_max`
        for the PDF at the lower and upper ends of the interval.
      - `cdf`: For slabs, the cumulative distribution function.
        If `options("ggdist.experimental.slab_data_in_intervals")` is `TRUE`:
        For intervals, the CDF at the point summary; intervals also have `cdf_min` and `cdf_max`
        for the CDF at the lower and upper ends of the interval.',
    if (isTRUE(stat$default_params$show_slab)) '
      - `n`: For slabs, the number of data points summarized into that slab. If the slab was created from
        an analytical distribution via the `xdist`, `ydist`, or `dist` aesthetic, `n` will be `Inf`.
      -  `f`: (deprecated) For slabs, the output values from the slab function (such as the PDF, CDF, or CCDF),
        determined by `slab_type`. Instead of using `slab_type` to change `f` and then mapping `f` onto an
        aesthetic, it is now recommended to simply map the corresponding computed variable (e.g. `pdf`, `cdf`, or
        `1 - cdf`) directly onto the desired aesthetic.
      ',
    if ("at" %in% names(stat$default_params)) '
      - `at`: For spikes, a character vector of names of the functions or expressions used to determine
        the points at which the slab functions were evaluated to create spikes. Values of this computed
        variable are determined by the `at` parameter; see its description above.
      ',
    if (inherits(stat, "StatMcseDots")) '
      - `se`: For dots, the Monte Carlo Standard Error of the quantile corresponding to each dot.
      '
  )

  out
}


# aesthetics --------------------------------------------------------------

#' Provides documentation of aesthetics for slabintervals
#' @noRd
rd_slabinterval_aesthetics = function(
  geom_name = "slabinterval",
  stat = NULL,
  vignette = "slabinterval"
) {

  out = glue_doc('
    @section Aesthetics:
    The slab+interval `stat`s and `geom`s have a wide variety of aesthetics that control
    the appearance of their three sub-geometries: the **slab**, the **point**, and
    the **interval**.

    ')

  out = c(out, rd_aesthetics_sections(geom_name, stat, vignette = vignette))

  glue_collapse(out, "\n")
}


# shared parameter docs ---------------------------------------------------

rd_param_slab_side = function() {
  paste0("@param side ", GeomSlabinterval$get_aes_docs()[["Slab-specific aesthetics"]]$side)
}
