#' @title
#' Constructing the product of posets.
#'
#' @description
#' Constructs the product poset \eqn{(V, \leq_{prd})}, starting from a collection of posets.
#'
#' @param poset1 An object of S4 class `POSet`.
#' Argument `poset1` must be created by using any function contained in the package
#' aimed at building object of S4 class `POSet`
#' (e.g. [POSet()], [LinearPOSet()], [ProductPOSet()], ...) .
#' @param poset2 An object of S4 class `POSet`.
#' Argument `poset2` must be created by using any function contained in the package
#' aimed at building object of S4 class `POSet`
#' (e.g. [POSet()], [LinearPOSet()], [ProductPOSet()], ...) .
#' @param ... Optional additional objects of S4 class `POSet`.
#' Optional arguments must be created by using any function contained in the package
#' aimed at building object of S4 class `POSet`
#' (e.g. [POSet()], [LinearPOSet()], [ProductPOSet()], ...) .
#'
#' @return
#' The product poset, an object of S4 class `ProductPOSet` (subclass of `POSet`).
#'
#' @details
#' Let \eqn{P_1 = (V_1, \leq_1), ..., P_k = (V_k, \leq_k)} be a collection of posets.
#' The product poset \eqn{P=P_1 \times...\times P_k} is the poset \eqn{(V, \leq_{prd})} where
#' \eqn{V=V_1\times...\times V_k} and given \eqn{(a_1, ..., a_k)\in V}
#' and \eqn{(b_1, ..., b_k)\in V},  \eqn{(a_1, ..., a_k)\leq_{prd} (b_1, ..., b_k)} if and only if
#' \eqn{a_i\leq_i b_i} for all \eqn{i=1, ..., k}.
#'
#' @examples
#' elems1 <- c("a", "b", "c", "d")
#' elems2 <- c("x", "y", "z")
#' elems3 <- c("q", "r")
#'
#' dom <- matrix(c(
#'   "a", "b",
#'   "c", "b",
#'   "b", "d"
#' ), ncol = 2, byrow = TRUE)
#'
#' p1 <- POSet(elements = elems1, dom = dom)
#' p2 <- LinearPOSet(elements = elems2)
#' p3 <- LinearPOSet(elements = elems3)
#'
#' prd12 <- ProductPOSet(p1, p2)
#'
#' prd123 <- ProductPOSet(p1, p2, p3)
#'
#' @name ProductPOSet
#' @export ProductPOSet
ProductPOSet <- function(poset1, poset2, ...) {
  if (!methods::is(poset1, "POSet")) {
    stop("Arguments poset1 must be of S4-class POSet")
  }
  if (!methods::is(poset2, "POSet")) {
    stop("Arguments poset2 must be of S4-class POSet")
  }
  for(p in list(...)) {
    if (!methods::is(p, "POSet")) {
      stop("Additional arguments must be of S4-class POSet")
    }
  }
  posets <- list()
  posets <- append(posets, poset1@ptr)
  posets <- append(posets, poset2@ptr)
  k <- 3
  for(p in list(...)) {
    posets <- append(posets, p@ptr)
    k <- k + 1
  }
  tryCatch({
    ptr <- .Call("_BuildProductPoset", posets)
    result <- methods::new("ProductPOSet", ptr = ptr)
    return (result)
  }, error = function(err) {
    err_split <- strsplit(err[[1]], split = ":")
    stop(err_split[[1]][length(err_split[[1]])])
  }) # END tryCatch
}
