#' @title Fuzzy in-betweenness array computation
#'
#' @description Starting from a poset dominance matrix, computes in-betweenness arrays by using a user supplied t-norm and t-conorm.
#'
#' @param dom square matrix representing the dominance degree between pairs of poset elements. Columns and rows names of `dom`
#' are interpreted as the labels of the poset elements. `dom` can be computed by using functions such as `BLSDominance`,
#' `BubleyByesMRP` and `ExactMRP`.
#'
#' @param norm R-function defining the t-norm
#'
#' @param conorm R-function defining the t-conorm
#'
#' @param type type of in-betweenness to be computed. Possible choices are:
#' "symmetric", "asymmetricLower", "asymmetricUpper".
#' For details on the definition of symmetric and asymmetric in-betweenness see Fattore et al. (2024).
#'
#' @param ... additional types of in-betweenness to be computed. Possible choices are:
#' "symmetric", "asymmetricLower", "asymmetricUpper".
#'
#'
#' @return a list of three-dimensional arrays, one array for each type of in-betweenness selected by parameter `type`.
#' The array element of position \eqn{[i,j,k]} represents \eqn{finb_{p_i,p_j,p_k}} for symmetric in-betweenness,
#' \eqn{finb_{p_i<p_j<p_k}} for asymmetricLower in-betweenness, and \eqn{finb_{p_k<p_j<p_i}} for asymmetricUpper in-betweenness.
#'
#' @references Fattore, M., De Capitani, L., Avellone, A., and Suardi, A. (2024).
#' A fuzzy posetic toolbox for multi-criteria evaluation on ordinal data systems.
#' Annals of Operations Research, https://doi.org/10.1007/s10479-024-06352-3.
#'
#' @examples
#' el <- c("a", "b", "c", "d")
#'
#' dom_list <- matrix(c(
#'   "a", "b",
#'   "c", "b",
#'   "b", "d"
#' ), ncol = 2, byrow = TRUE)
#'
#' pos <- POSet(elements = el, dom = dom_list)
#'
#' BLS <- BLSDominance(pos)
#'
#' tnorm <- function(x,y){x*y}
#'
#' tconorm <- function(x,y){x+y-x*y}
#'
#' FinB <- FuzzyInBetweenness(BLS, norm=tnorm, conorm=tconorm, type="symmetric", "asymmetricLower")
#'
#' @name FuzzyInBetweenness
#' @export FuzzyInBetweenness
FuzzyInBetweenness <- function(dom, norm, conorm, type, ...) {
  SeparationTypes <- c("symmetric", "asymmetricLower", "asymmetricUpper")
  SeparationTypesC <- c("symmetric", "asymmetricLower", "asymmetricUpper")
  if (!is.matrix(dom)) {
    stop("dom must be a square matrix")
  }
  if (ncol(dom) != nrow(dom)) {
    stop("dom must be a square matrix")
  }

  if (!methods::is(norm, "function")) {
    out_str <- paste("Arguments must be a R-function.", collapse=", ")
    stop(out_str)
  }

  if (!methods::is(conorm, "function")) {
    out_str <- paste("Arguments must be a R-function.", collapse=", ")
    stop(out_str)
  }

  if (!(type %in% SeparationTypes)) {
    stop("type TO_DO")
  }
  parameter_list = list(type)
  for(t in list(...)) {
    if (!(t %in% SeparationTypes)) {
      stop(".... TO_DO")
    }
    parameter_list[[length(parameter_list)+1]] = t
  }

  functions_list <- parameter_list
  if (SeparationTypes[4] %in% parameter_list) {
    functions_list[[length(functions_list)+1]] = SeparationTypes[2]
    functions_list[[length(functions_list)+1]] = SeparationTypes[3]
  }
  if (SeparationTypes[5] %in% parameter_list) {
    functions_list[[length(functions_list)+1]] = SeparationTypes[1]
    functions_list[[length(functions_list)+1]] = SeparationTypes[2]
    functions_list[[length(functions_list)+1]] = SeparationTypes[3]
  }
  functions_list <- intersect(functions_list, SeparationTypesC)

  tryCatch({
    result <- .Call("_FuzzyInBetweenness", dom, norm, conorm, functions_list)
    if ("vertical" %in% parameter_list) {
      vertical <- abs(result[["asymmetricLower"]] - result[["asymmetricUpper"]])
      result[["vertical"]] = vertical
    }
    if ("horizontal" %in% parameter_list) {
      horizzotal <- result[["symmetric"]] - (abs(result[["asymmetricLower"]] - result[["asymmetricUpper"]]))
      result[["horizontal"]] = horizzotal
    }
    if ("symmetric" %in% parameter_list) {
      horizzotal <- result[["symmetric"]] - (abs(result[["asymmetricLower"]] - result[["asymmetricUpper"]]))
      result[["horizontal"]] = horizzotal
    }
    result <- result[unlist(parameter_list)]
    return (result)
  }, error = function(err) {
    err_split <- strsplit(err[[1]], split = ":")
    stop(err_split[[1]][length(err_split[[1]])])
  }) # END tryCatch
}
