#' @title
#' Separation matrices computation over the set of lexicographic linear extensions.
#'
#' @description Considering the component-wise poset built stating from \eqn{k} ordinal variables,
#'  computes separation matrices by analyzing all poset lexicographic linear extensions.
#'
#' @param nvar positive integer specifying the number \eqn{k} of ordinal variables.
#'
#' @param deg parameter specifying the number of degrees of each variable. If all \eqn{k} variables have the same number \eqn{m} of degrees, it can be:
#' 1) the positive integer \eqn{m}. In this case variable degree labels are supposed to be the integers \eqn{0<1<...<m}
#' and columns and rows of computed separation matrices are named accordingly to this;
#' 2) a character vector of length \eqn{m} specifying the variable degree labels (in this case columns and rows of computed separation matrices are
#' named accordingly to \code{deg}).
#'
#' If the \eqn{k} variables have different number \eqn{(m_1,...,m_k)} of degrees, it can be:
#' 1) a length-\eqn{k} positive integers vector specifying the values of \eqn{m_1,...,m_k}. In this case variable degree labels for the \eqn{j}-th variable are
#' supposed to be the integers \eqn{0<1<...<m_j} and columns and rows of computed separation matrices are named accordingly to this;
#' 2) a list of \eqn{k} character vectors. The \eqn{j}-th list element is a character vector of length \eqn{m_j} specifying the degree labels for the \eqn{j}-th variable
#' (in this case columns and rows of computed separation matrices are named accordingly to \code{deg}).
#'
#' @param type type of separation matrix to be computed. Possible choices are:
#' "symmetric", "asymmetricLower", "asymmetricUpper", "vertical", "horizontal".
#'
#'
#' @param ... additional types of separations to be computed. Possible choices are:
#' "symmetric", "asymmetricLower", "asymmetricUpper", "vertical", "horizontal".
#'
#' @return list of required separation matrices.
#'
#' @examples
#'
#' #variables with common number of degrees
#' # default labels for variable degrees
#' nvar <- 3
#' deg  <- 4
#' LexSep <- LexSeparation(nvar=nvar, deg=deg, type= "symmetric", "asymmetricLower")
#'
#' #user supplied variable degree labels
#' nvar <- 3
#' deg  <- c("a","b","c","d")
#' LexSep <- LexSeparation(nvar=nvar, deg=deg, type= "symmetric", "asymmetricLower")
#'
#'
#' #variables with different numbers of degrees
#' # default labels for variable degrees
#' nvar <- 3
#' deg  <- c(4,2,3)
#' LexSep <- LexSeparation(nvar=nvar, deg=deg, type= "symmetric", "asymmetricLower")
#'
#' #user supplied variable degree labels
#' nvar <- 3
#' deg  <- list(c("a","b","c","d"),c("0","1"),c("x","y","z"))
#' LexSep <- LexSeparation(nvar=nvar, deg=deg, type= "symmetric", "asymmetricLower")
#'
#' @name LexSeparation
#' @export LexSeparation
LexSeparation <- function(nvar, deg, type, ...) {
  SeparationTypes <- c("symmetric", "asymmetricLower", "asymmetricUpper", "vertical", "horizontal")
  if ((length(nvar) != 1 || nvar <= 0 || nvar != round(nvar))) {
    stop("nvar must be a positive integer")
  }
  nvar <- as.integer(nvar)

  if (
    !(
      (is.numeric(deg) && length(deg) == 1 && deg > 0 && deg == round(deg))      # positive integer
      || is.character(deg)   # a character array
      || (is.numeric(deg) && length(deg) == nvar && all(deg > 0) && all(deg == round(deg)))  # positive integer array
      || (is.list(deg) && length(deg) == nvar && all(sapply(deg, is.character)))  # list of character array
    )
  ) {
    stop(paste("deg must be a positive integer or a character array or a positive integer array of length ", nvar , " or a list of length ", nvar , " of character array.", sep=""))
  }
  if ((is.numeric(deg) && length(deg) == 1 && deg > 0 && deg == round(deg))) {
    deg <- replicate(nvar, as.character(1:deg), simplify = FALSE)
  } else if (is.character(deg)) {
    deg <- replicate(nvar, deg, simplify = FALSE)
  } else if ((is.numeric(deg) && length(deg) == nvar && all(deg > 0) && all(deg == round(deg)))) {
    deg <- sapply(deg, function(x) as.character(1:x))
  } else {
    deg<- as.list(deg)
  }

  if (!(type %in% SeparationTypes)) {
    stop(paste("type must be one of ", SeparationTypes, sep=""))
  }
  parameter_list = list(type)
  for(t in list(...)) {
    if (!(t %in% SeparationTypes)) {
      stop(paste("... must be one of ", SeparationTypes, sep=""))
    }
    parameter_list[[length(parameter_list)+1]] = t
  }
  tryCatch({
    result <- .Call("_LexSeparation", deg)
    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
}
