#' parallel version of part-of-speech tagger
#'
#' \code{posParallel} returns part-of-speech (POS) tagged morpheme of the sentence.
#'
#' This is a parallelized version of MeCab part-of-speech tagger. The function gets a
#' character vector of any length and runs a loop inside C++ with Intel TBB to provide faster
#' processing.
#'
#' Parallelizing over a character vector is not supported by \code{RcppParallel}.
#' Thus, this function makes duplicates of the input and the output.
#' Therefore, if your data volume is large, use \code{pos} or divide the vector to
#' several sub-vectors.
#'
#' You can add a user dictionary to \code{user_dic}. It should be compiled by
#' \code{mecab-dict-index}. You can find an explanation about compiling a user
#' dictionary in the \url{https://github.com/junhewk/RcppMeCab}.
#'
#' You can also set a system dictionary especially if you are using multiple
#' dictionaries (for example, using both IPA and Juman dictionary at the same time in Japanese)
#' in \code{sys_dic}. Using \code{options(mecabSysDic=)}, you can set your
#' preferred system dictionary to the R terminal.
#'
#' The \code{lang} argument selects a dictionary; it does not switch the MeCab
#' engine chosen when RcppMeCab was installed. Japanese and Chinese dictionaries
#' use standard MeCab. Supported Korean behavior, including mecab-ko whitespace
#' handling, requires the mecab-ko engine. Dictionary feature layouts are
#' language-specific, and the historical data-frame columns do not expose all
#' mecab-jieba metadata.
#'
#' If you want to get a morpheme only, use \code{join = False} to put tag names on the attribute.
#' Basically, the function will return a list of character vectors with (morpheme)/(tag) elements.
#'
#' @param sentence A character vector of any length. For analyzing multiple sentences, put them in one character vector.
#' @param join A bool to decide the output format. The default value is TRUE. If FALSE, the function will return morphemes only, and tags put in the attribute. if \code{format="data.frame"}, then this will be ignored.
#' @param format A data type for the result. The default value is "list". You can set this to "data.frame" to get a result as data frame format.
#' @param lang Optional dictionary code (\code{"ja"}, \code{"ko"}, or
#'   \code{"zh"}) selecting a dictionary installed via
#'   \code{\link{download_dic}}. This does not switch the MeCab engine. When
#'   specified, it overrides \code{sys_dic}.
#' @param sys_dic A location of system MeCab dictionary. The default value is "".
#' @param user_dic A location of user-specific MeCab dictionary. The default value is "".
#' @return A string vector or a list of POS tagged morpheme will be returned in conjoined character
#'  vector form.
#'
#' @examples
#' \dontrun{
#' sentence <- c(#some UTF-8 texts)
#' posParallel(sentence)
#' posParallel(sentence, join = FALSE)
#' posParallel(sentence, format = "data.frame")
#' posParallel(sentence, lang = "ja")
#' posParallel(sentence, lang = "zh")
#' posParallel(sentence, sys_dic = "/path/to/custom/dic")
#' posParallel(sentence, user_dic = "/path/to/user.dic")
#' }
#'
#' @export
posParallel <- function(sentence, join = TRUE, format = c("list", "data.frame"), lang = NULL, sys_dic = "", user_dic = "") {
  if (typeof(sentence) != "character") {
    if (typeof(sentence) == "factor") {
      stop("The type of input sentence is a factor. Please typesetting it with as.character().")
    } else {
      stop("The function gets a character vector only.")
    }
  }

  if (!is.null(lang)) {
    sys_dic <- .resolve_dic(match.arg(lang, c("ja", "ko", "zh")))
  } else if (!is.null(getOption("mecabSysDic")) && sys_dic == "") {
    sys_dic <- getOption("mecabSysDic")
  }

  format = match.arg(format)

  if (format == "data.frame") {
    result <- posParallelDFRcpp(sentence, sys_dic, user_dic)
  } else {
    if (join == TRUE) {
      result <- posParallelJoinRcpp(sentence, sys_dic, user_dic)
    } else {
      result <- posParallelRcpp(sentence, sys_dic, user_dic)
    }
  }

  return(result)
}
