#' Group by individual matrix
#'
#' `get_gbi` generates a group by individual matrix. The function expects a
#' `data.table` with individual identifiers and a group column. The group
#' by individual matrix can then be used to build a network using
#' [asnipe::get_network()].
#'
#' The `DT` must be a `data.table`. If your data is a
#' `data.frame`, you can convert it by reference using
#' [data.table::setDT()].
#'
#' The `group` argument expects the name of a column which corresponds to
#' an integer group identifier (generated by `spatsoc`'s grouping
#' functions).
#'
#' The `id` argument expects the name of a column which corresponds to the
#' individual identifier.
#'
#' @return `get_gbi` returns a group by individual matrix (columns
#'   represent individuals and rows represent groups).
#'
#'   Note that `get_gbi` is identical in function for turning the outputs
#'   of `spatsoc` into social networks as
#'   [asnipe::get_group_by_individual()]
#'   but is more efficient thanks to
#'   [`data.table::dcast()`][data.table::dcast.data.table].
#'
#' @inheritParams group_pts
#' @param group Character string of group column (generated from one of
#'   spatsoc's spatial grouping functions)
#' @export
#'
#' @seealso `group_pts` `group_lines`
#'   `group_polys`
#' @family Social network tools
#'
#' @examples
#' # Load data.table
#' library(data.table)
#' \dontshow{data.table::setDTthreads(1)}
#'
#' # Read example data
#' DT <- fread(system.file("extdata", "DT.csv", package = "spatsoc"))
#'
#' # Cast the character column to POSIXct
#' DT[, datetime := as.POSIXct(datetime, tz = 'UTC')]
#' DT[, yr := year(datetime)]
#'
#' # EPSG code for example data
#' utm <- 'EPSG:32736'
#'
#' group_polys(DT, area = FALSE, hrType = 'mcp',
#'             hrParams = list(percent = 95),
#'             crs = utm, id = 'ID', coords = c('X', 'Y'),
#'             splitBy = 'yr')
#'
#' gbiMtrx <- get_gbi(DT = DT, group = 'group', id = 'ID')
#'
get_gbi <- function(DT = NULL,
    group = 'group',
    id = NULL) {

  assert_not_null(DT)
  assert_is_data_table(DT)
  assert_not_null(group)
  assert_not_null(id)
  assert_are_colnames(DT, c(group, id))

  if (anyNA(DT[[group]])) {
    warning('DT contains NA(s) in group column, these rows will be dropped')
  }

  uDT <-
    stats::na.omit(unique(DT[, .SD, .SDcols = c(group, id)]),
            cols = group)

  cDT <-
    data.table::dcast(
      uDT,
      formula = stats::reformulate(id, group),
      fun.aggregate = length,
      value.var = group
    )

  ids <- colnames(cDT)[!grepl(group, colnames(cDT))]

  m <- as.matrix(cDT[, .SD, .SDcols = ids])

  rownames(m) <- cDT[[group]]
  return(m)
}
