#' Leadership in directional correlation delay
#'
#' Given the directional correlation delay, `leader_edge_delay`
#' calculates the mean directional correlation delay for individuals in a
#' group to identify leadership patterns.
#'
#' The function expects an edge-list from `edge_delay` with columns
#' 'direction_delay' indicating the directional correlation delay between
#' individuals and 'direction_diff' indicating the unsigned difference in
#' movement directions at the temporal delay, columns 'ID1' and 'ID2' indicating
#' individuals and column 'dyadID' indicating the dyad.
#'
#' The `edge` must be a `data.table`. If your data is a
#' `data.frame`, you can convert it by reference using
#' [data.table::setDT()] or by reassigning using
#' [data.table::data.table()].
#'
#' @return `leader_edge_delay` returns the input `edges` aggregated
#'   with a `mean_direction_delay_dyad` column indicating the mean
#'   directional correlation delay between ID1 and ID2 and a
#'   `mean_direction_delay` column indicating the mean directional
#'   correlation delay for each individual in 'ID1' column.
#'
#'  Note: since `leader_edge_delay` returns an aggregation of the input
#'  `edges`, the output needs to be reassigned unlike some other
#'  `spatsoc` functions like `dyad_id`. See details in
#'  [FAQ](https://docs.ropensci.org/spatsoc/articles/faq.html).
#'
#'
#' @inheritParams edge_delay
#' @param threshold (optional) threshold difference in direction used to subset
#'   rows included in calculation of mean directional delay. eg.
#'   `threshold = 0.5` corresponds to only rows where direction_diff is
#'   less than 0.5. Expects that unit is radians, see `edge_delay`.
#' @param splitBy (optional) character string or vector of grouping column
#'   name(s) upon which the mean directional correlation delay will be
#'   calculated
#'
#' @export
#' @seealso `edge_delay`
#' @family Leadership functions
#' @family Direction functions
#'
#' @references
#' See examples of measuring leadership using the directional correlation
#' delay:
#'  * \doi{doi:10.1016/j.anbehav.2013.07.005}
#'  * \doi{doi:10.1073/pnas.1305552110}
#'  * \doi{doi:10.1126/science.aap7781}
#'  * \doi{doi:10.1111/jfb.15315}
#'  * \doi{doi:10.1371/journal.pcbi.1003446}
#'
#' @examples
#' # Load data.table
#' library(data.table)
#' \dontshow{data.table::setDTthreads(1)}
#'
#' # Read example data
#' DT <- fread(system.file("extdata", "DT.csv", package = "spatsoc"))
#'
#' # Select only individuals A, B, C for this example
#' DT <- DT[ID %in% c('A', 'B', 'C')]
#'
#' # Cast the character column to POSIXct
#' DT[, datetime := as.POSIXct(datetime, tz = 'UTC')]
#'
#' # Temporal grouping
#' group_times(DT, datetime = 'datetime', threshold = '20 minutes')
#'
#' # Calculate direction
#' direction_step(
#'   DT = DT,
#'   id = 'ID',
#'   coords = c('X', 'Y'),
#'   crs = 32736
#' )
#'
#' # Distance based edge-list generation
#' edges <- edge_dist(
#'   DT,
#'   threshold = 100,
#'   id = 'ID',
#'   coords = c('X', 'Y'),
#'   timegroup = 'timegroup',
#'   returnDist = TRUE,
#'   fillNA = FALSE
#' )
#'
#' # Generate dyad id
#' dyad_id(edges, id1 = 'ID1', id2 = 'ID2')
#'
#' # Generate fusion id
#' fusion_id(edges, threshold = 100)
#'
#' # Directional correlation delay
#' delay <- edge_delay(
#'   edges = edges,
#'   DT = DT,
#'   window = 3,
#'   id = 'ID'
#' )
#'
#' # Leadership from directional correlation delay
#' leadership <- leader_edge_delay(
#'   delay,
#'   threshold = 0.5
#' )
#' print(leadership)
#'
#' # Or, using the new geometry interface
#' get_geometry(DT, coords = c('X', 'Y'), crs = 32736)
#' direction_step(DT, id = 'ID')
#' edges <- edge_dist(DT, threshold = 100, id = 'ID', timegroup = 'timegroup', returnDist = TRUE)
#' dyad_id(edges, id = 'ID1', id2 = 'ID2')
#' fusion_id(edges, threshold = 100)
#' delay <- edge_delay(
#'   edges = edges,
#'   DT = DT,
#'   window = 3,
#'   id = 'ID'
#' )
#' leadership <- leader_edge_delay(
#'   delay,
#'   threshold = 0.5
#' )
#' print(leadership)
leader_edge_delay <- function(
    edges = NULL,
    threshold = NULL,
    splitBy = NULL) {
  # Due to NSE notes
  . <- direction_diff <- direction_delay <- mean_direction_delay <-
    mean_direction_delay_dyad <- NULL
  direction_delay <- 'direction_delay'
  direction_diff <- 'direction_diff'

  assert_not_null(edges)
  assert_is_data_table(edges)

  check_cols <- c(direction_delay, direction_diff, 'ID1', 'ID2', splitBy)
  assert_are_colnames(edges, check_cols, ', did you use edge_delay?')
  assert_col_inherits(edges, direction_delay, 'integer',
                      ', did you use edge_delay?')
  assert_col_inherits(edges, direction_diff, 'numeric',
                      ', did you use edge_delay?')

  if (is.null(threshold)) {
    threshold <- Inf
  } else {
    assert_inherits(threshold, 'numeric')
  }

  subset_threshold <- edges[direction_diff < threshold]

  out <- subset_threshold[,
    .(mean_direction_delay_dyad = mean(direction_delay, na.rm = TRUE)),
    by = c('ID1', 'ID2', 'dyadID', splitBy)]

  out[, mean_direction_delay := mean(mean_direction_delay_dyad, na.rm = TRUE),
      by = c('ID1', splitBy)]

  return(out[])
}
