#' @title Plot Single Luminescence Curves from a Risoe.BINfileData-class object
#'
#' @description
#' Plots single luminescence curves from a [Risoe.BINfileData-class] object
#' produced by [read_BIN2R].
#'
#' @details
#' **Nomenclature**
#'
#' See [Risoe.BINfileData-class]
#'
#' **curve.transformation**
#'
#' This argument allows transforming continuous wave (CW) curves to pseudo
#' (linear) modulated curves. For the transformation, the functions of the
#' package are used.  Currently, it is not possible to pass further arguments
#' to the transformation functions. The argument works only for `ltype`
#' `OSL` and `IRSL`.
#'
#' **Irradiation time**
#'
#' Plotting the irradiation time (s) or the given dose (Gy) requires that the
#' variable `IRR_TIME` has been set within the BIN-file.  This is normally
#' done by using the 'Run Info' option within the Sequence Editor or by editing
#' in R.
#'
#' @param data [Risoe.BINfileData-class] (**required**):
#' an S4 object generated by the [read_BIN2R] function.
#'
#' @param position [vector] (*optional*):
#' option to limit the plotted curves by position
#' (e.g. `position = 1`, `position = c(1,3,5)`).
#'
#' @param run [vector] (*optional*):
#' option to limit the plotted curves by run
#' (e.g., `run = 1`, `run = c(1,3,5)`).
#'
#' @param set [vector] (*optional*):
#' option to limit the plotted curves by set
#' (e.g., `set = 1`, `set = c(1,3,5)`).
#'
#' @param sorter [character] (*with default*):
#' ordering used in plotting the curves, one of "POSITION", "SET" or "RUN".
#' POSITION, SET and RUN are options defined in the Risoe Sequence Editor.
#'
#' @param ltype [character] (*with default*):
#' option to limit the plotted curves by the type of luminescence stimulation.
#' Allowed values: `"IRSL"`, `"OSL"`,`"TL"`, `"RIR"`, `"RBR"`
#' (corresponds to LM-OSL), `"RL"`.  All type of curves are plotted by
#' default.
#'
#' @param curve.transformation [character] (*optional*):
#' allows transforming CW-OSL and CW-IRSL curves to pseudo-LM curves via
#' transformation functions. Allowed values are: `CW2pLM`, `CW2pLMi`,
#' `CW2pHMi` and `CW2pPMi`, see details. If set to `None` (default), no
#' transformation is applied.
#'
#' @param dose_rate [numeric] (*optional*):
#' dose rate of the irradiation source at the measurement date.
#' If set, the given irradiation dose will be shown in Gy.  See details.
#'
#' @param temp.lab [character] (*with default*):
#' the temperature unit to display in the plot labels, by default deg C.
#'
#' @param cex.global [numeric] (*with default*):
#' global scaling factor.
#'
#' @param ... further undocumented plot arguments.
#'
#' @return Returns a plot.
#'
#' @note
#' The function has been successfully tested for the Sequence Editor file
#' output version 3 and 4.
#'
#' @section Function version: 0.4.3
#'
#' @author
#' Sebastian Kreutzer, Institute of Geography, Heidelberg University (Germany)\cr
#' Michael Dietze, GFZ Potsdam (Germany)\cr
#' Marco Colombo, Institute of Geography, Heidelberg University (Germany)
#'
#' @seealso [Risoe.BINfileData-class], [read_BIN2R], [convert_CW2pLM],
#' [convert_CW2pLMi], [convert_CW2pPMi], [convert_CW2pHMi]
#'
#' @references
#' Duller, G., 2007. Analyst. pp. 1-45.
#'
#' @keywords dplot
#'
#' @examples
#'
#' ##load data
#' data(ExampleData.BINfileData, envir = environment())
#'
#' ##plot all curves from the first position to the desktop
#' #pdf(file = "~/Desktop/CurveOutput.pdf", paper = "a4", height = 11, onefile = TRUE)
#'
#' ##example - load from *.bin file
#' #BINfile<- file.choose()
#' #BINfileData<-read_BIN2R(BINfile)
#'
#' #par(mfrow = c(4,3), oma = c(0.5,1,0.5,1))
#' #plot_Risoe.BINfileData(CWOSL.SAR.Data,position = 1)
#' #mtext(side = 4, BINfile, outer = TRUE, col = "blue", cex = .7)
#' #dev.off()
#'
#' @export
plot_Risoe.BINfileData<- function(
  data,
  position = NULL,
  run = NULL,
  set = NULL,
  sorter = "POSITION",
  ltype = c("IRSL","OSL","TL","RIR","RBR","RL"),
  curve.transformation = "None",
  dose_rate = NULL,
  temp.lab = "\u00B0C",
  cex.global = 1,
  ...
) {
  .set_function_name("plot_Risoe.BINfileData")
  on.exit(.unset_function_name(), add = TRUE)

  ## Integrity checks -------------------------------------------------------

  .validate_class(data, "Risoe.BINfileData")
  .validate_class(position, c("integer", "numeric"), null.ok = TRUE)
  .validate_class(run, c("integer", "numeric"), null.ok = TRUE)
  .validate_class(set, c("integer", "numeric"), null.ok = TRUE)
  .validate_args(sorter, c("POSITION", "RUN", "SET"))
  .validate_length(sorter, 1)
  .validate_positive_scalar(dose_rate, null.ok = TRUE)
  curve.transformation <- .validate_args(curve.transformation,
                                         c("CW2pLM", "CW2pLMi",
                                           "CW2pHMi", "CW2pPMi", "None"))
  ## complete the function name
  if (curve.transformation != "None") {
    curve.transformation <- paste0("convert_", curve.transformation)
  }

  temp <- data@METADATA

  ## set values for missing arguments
  if (is.null(position))
    position <- sort(unique(temp[, "POSITION"]))
  if (is.null(run))
    run <- sort(unique(temp[, "RUN"]))
  if (is.null(set))
    set <- sort(unique(temp[, "SET"]))

  fun <- isTRUE(list(...)$fun)

  ## Plot -------------------------------------------------------------------

  ## keep only the curves to plot
  temp <- temp[temp[, "POSITION"] %in% position &
               temp[, "RUN"] %in% run &
               temp[, "SET"] %in% set &
               temp[, "LTYPE"] %in% ltype, ]

  ## order by RUN, SET OR BY POSITION
  temp <- temp[order(temp[, sorter]), ]

  ## plot the selected curves
  for (i in seq_len(nrow(temp))) {
      high <- temp[i, "HIGH"]
      npoints <- temp[i, "NPOINTS"]
      ltype <- temp[i, "LTYPE"]
      is.TL <- ltype == "TL"
      measured_unit <- if (is.TL) temp.lab else "s"

      ##set x and y values
      values.xy <- data.frame(x = seq(high / npoints, high, by = high / npoints),
                              y = unlist(data@DATA[temp[i, "ID"]]))

      ##set curve transformation if wanted
      if (grepl("IRSL|OSL", ltype) &&
          curve.transformation != "None") {

        ## get the actual function from the parameter value and apply it
        values.xy <- get(curve.transformation)(values.xy)[, 1:2]
      }

      ##plot graph
      plot(values.xy,
           main = paste0("pos=", temp[i, "POSITION"],
                         ", run=", temp[i, "RUN"],
                         ", set=", temp[i, "SET"]),
           type="l",
           xlab = if (is.TL) paste0("Temperature [", temp.lab, "]") else "Time [s]",
           ylab = paste0(ltype, " [cts/", round(high / npoints, 3),
                         " ", measured_unit, "]"),
           col = if (ltype %in% c("IRSL", "RIR")) "red"
                 else if (ltype %in% c("OSL", "RBR")) "blue"
                 else "black",
           sub = if (is.TL) paste0("(", temp[i, "RATE"], " K/s)"),
           lwd=1.2*cex.global,
           cex=0.9*cex.global
      )

      ##add mtext for temperature
      temp.field <- if (temp[i, "VERSION"] == "03") "AN_TEMP" else "TEMPERATURE"
      temperature <- temp[i, temp.field]
      mtext(side=3,
            if (is.TL) paste("TL to", high, temp.lab)
            else paste0(ltype, "@", temperature, " ", temp.lab),
            cex=0.9*cex.global)

      ##add mtext for irradiation
      if (temp[i, "IRR_TIME"] != 0) {
        mtext(side = 4, cex = 0.8 * cex.global, line = 0.5,
              if (is.null(dose_rate))
                paste("dose =", temp[i, "IRR_TIME"], "s")
              else
                paste("dose =", temp[i, "IRR_TIME"] * dose_rate, "Gy")
              )
      }
  }#endforloop

  if (fun) sTeve() # nocov
}
