#' Differential Analysis using `DESeq2` or `edgeR`
#'
#' @description `RNAdifferentialAnalysis` function computes the differential 
#' analysis with `DESeq2` or `edgeR` of sRNA or mRNA data produced by the 
#' `mobileRNA` package pipeline.  
#'
#' @param data data.frame; originally generated by [mobileRNA::RNAimport()].
#'
#' @param group character; the condition of each sample in the experimental 
#' design, formatted in the order of samples shown in the `data` object from 
#' left to right.
#'
#' @param method character; method to undertaken differential analysis, choose 
#' from methods of either [DESeq2::DESeq] or [edgeR::edgeR].
#' Must be stated as either "DESeq2" or "edgeR" in the function.
#'
#' @param dispersionValue numeric; value to represent the dispersion value for
#' the [edgeR::edgeR] method. Recommended for analysis in experiments without 
#' biological replicates. 
#'
#' @return Undertakes differential analysis, based on a specified method, and
#' appends the results to the supplied data frame. This includes:
#' * Count mean 
#' * Log fold change
#' * p-value
#' * Adjusted p-value
#' * Comparison order 
#'
#' @details The user has the flexibility to choose the method that best suits
#' their data. In this function, the `DESeq2` method, calculates the 
#' differentials based on the normalized count data based on the 
#' size factors. Whereas the `edgeR` method, calculates normalization factors
#' estimates dispersion, and returns the common dispersion. After
#' normalization, the mean expression levels across samples are calculated, and 
#' differential expression analysis is performed using the exact test 
#' within groups, and the adjusted p-values are calculated using the 
#' Benjamini-Hochberg method. Note that this function is only capable of 
#' handling one replicate per condition with the `edgeR` method. This requires 
#' setting a suitable dispersion value. The dispersion value is other wise known 
#' as the common Biological squared coefficient of variation. See the 
#' User’s Guide for the `edgeR` package for more details, [edgeR::edgeR].
#'
#' @examples
#'# load data 
#' data("sRNA_data")
#' 
#' 
#'# sample conditions.
#'groups <- c("Selfgraft", "Selfgraft", "Selfgraft", "Heterograft", "Heterograft", "Heterograft")
#'
#'
#'## Differential analysis: DEseq2 method
#'sRNA_DESeq2 <- RNAdifferentialAnalysis(data = sRNA_data,
#'                              group = groups,
#'                              method = "DESeq2" )
#'
#'
#'## Differential analysis: edgeR method
#'sRNA_edgeR <- RNAdifferentialAnalysis(data = sRNA_data,
#'                             group = groups,
#'                             method = "edgeR" )
#' @export
#' @importFrom DESeq2 results
#' @importFrom DESeq2 DESeq
#' @importFrom stats relevel
#' @importFrom edgeR exactTest
#' @importFrom stats p.adjust
#' @importFrom dplyr select
#' @importFrom tidyselect starts_with
#' @importFrom dplyr mutate_at
#' @importFrom tidyr replace_na
#' @importFrom DESeq2 DESeqDataSetFromMatrix
#' @importFrom DESeq2 estimateSizeFactors
#' @importFrom edgeR DGEList
#' @importFrom edgeR calcNormFactors
#' @importFrom edgeR estimateDisp

RNAdifferentialAnalysis <- function(data, group, 
                                    method = c("edgeR", "DESeq2"),
                                    dispersionValue = NULL){
  if (base::missing(data) || !base::inherits(data,  "data.frame")) {
    stop("Please specify a data frame")
  }
  if (base::missing(method) || !method %in% c("edgeR", "DESeq2")) {
    stop("Please specify analysis method", "(\"edgeR\", or \"DESeq2\")")
  }
  if ( is.null(group) || !base::inherits(group, "character")) {
    stop("group must be an vector of characters to specify the treatment
         and control conditions for each replicate")
  }
  counts <- data %>% dplyr::select(tidyselect::starts_with("Count"))
  method <- base::match.arg(method)
  if(method == "edgeR"){
    message("Undertaking differential analysis with the edgeR method..")
    res <-  .edgeR_normalise(counts, group)
    if(is.null(dispersionValue)){
      mean <- rowMeans(res$counts)
      groupConditions <- unique(group)
      comp <- edgeR::exactTest(res, pair= groupConditions)
      comp <- base::cbind(comp$table, padj=stats::p.adjust(comp$table$PValue,
                                                           method="BH"))
      comp$CountMean <- mean
    } else {
      comp <- edgeR::exactTest(res, dispersion=dispersionValue^2)
      comp <- base::cbind(comp$table, padj=stats::p.adjust(comp$table$PValue,
                                                           method="BH"))
    }
    data$CountMean <- comp$CountMean
    data$log2FoldChange <- comp$logFC
    data$pvalue <- comp$PValue
    data$padjusted <- comp$padj
    #data$logCPM <- comp$logCPM
  } else
    if (method == "DESeq2"){
      message("Undertaking differential analysis with the DESeq2 method..")
      res <- .DESeq_normalise(counts, group)
      comp <- DESeq2::DESeq(res)
      comp <- DESeq2::results(comp)
      data$CountMean <- comp[,"baseMean"]
      data$log2FoldChange <- comp[,"log2FoldChange"]
      data$pvalue <- comp[,"pvalue"]
      data$padjusted <- comp[,"padj"]
    }
  res.df <- data %>%
    dplyr::mutate_at(c('log2FoldChange','padjusted', 'pvalue'),
                     ~tidyr::replace_na(.,0))
  comparision.order <- paste(unique(groups),  collapse = " Vs ")
  res.df$comparision.order <- comparision.order
    
  return(res.df)
}
