#' @title Trigger Evaluation of Custom Function
#'
#' @description
#' Hooks allow to trigger functions calls on specific events.
#' They can be specified via the \code{\link{ClusterFunctions}} and are triggered on the following events:
#' \describe{
#'   \item{\code{pre.sync}}{\code{function(reg, fns, ...)}: Run before synchronizing the registry on the master. \code{fn} is the character vector of paths to the update files.}
#'   \item{\code{post.sync}}{\code{function(reg, updates, ...)}: Run after synchronizing the registry on the master. \code{updates} is the data.table of processed updates.}
#'   \item{\code{pre.submit.job}}{\code{function(reg, ...)}: Run before a job is successfully submitted to the scheduler on the master.}
#'   \item{\code{post.submit.job}}{\code{function(reg, ...)}: Run after a job is successfully submitted to the scheduler on the master.}
#'   \item{\code{pre.submit}}{\code{function(reg, ...)}: Run before any job is submitted to the scheduler.}
#'   \item{\code{post.submit}}{\code{function(reg, ...)}: Run after a jobs are submitted to the schedule.}
#'   \item{\code{pre.do.collection}}{\code{function(reg, reader, ...)}: Run before starting the job collection on the slave.
#'     \code{reader} is an internal cache object.}
#'   \item{\code{post.do.collection}}{\code{function(reg, updates, reader, ...)}: Run after all jobs in the chunk are terminated on the slave.
#'     \code{updates} is a \code{\link{data.table}} of updates which will be merged with the \code{\link{Registry}} by the master.
#'     \code{reader} is an internal cache object.}
#'   \item{\code{pre.kill}}{\code{function(reg, ids, ...)}: Run before any job is killed.}
#'   \item{\code{post.kill}}{\code{function(reg, ids, ...)}: Run after jobs are killed. \code{ids} is the return value of \code{\link{killJobs}}.}
#' }
#'
#' @param obj [\link{Registry} | \link{JobCollection}]\cr
#'  Registry which contains the \link{ClusterFunctions} with element \dQuote{hooks}
#'  or a \link{JobCollection} which holds the subset of functions which are executed
#'  remotely.
#' @param hook [\code{character(1)}]\cr
#'  ID of the hook as string.
#' @param ... [ANY]\cr
#'  Additional arguments passed to the function referenced by \code{hook}.
#'  See description.
#' @return Return value of the called function, or \code{NULL} if there is no hook
#'  with the specified ID.
#' @aliases Hooks Hook
#' @export
runHook = function(obj, hook, ...) {
  UseMethod("runHook")
}

#' @export
runHook.Registry = function(obj, hook, ...) {
  f = obj$cluster.functions$hooks[[hook]]
  if (is.null(f))
    return(NULL)
  "!DEBUG [runHook]: Running hook '`hook`'"
  f(obj, ...)
}

#' @export
runHook.JobCollection = function(obj, hook, ...) {
  f = obj$hooks[[hook]]
  if (is.null(f))
    return(NULL)
  "!DEBUG [runHook]: Running hook '`hook`'"
  f(obj, ...)
}
