#' PCA plot of PC1 and PC2
#'
#' @description Draws a principal component analysis (PCA) plot of PC1 and PC2. 
#' The function undertakes rlog transformation of the data in an unbiased manner
#'  (\code{blind=TRUE}).
#'
#' @param data data.frame; originally generated by [mobileRNA::RNAimport()] 
#' 
#' @param group character; contains experimental conditions for each
#' replicate. 
#' 
#' *IMPORTANT*: Ensure this is in the same order as the replicates are
#' found in the data frame supplied to the `data` argument (from left to right).
#'
#' @param vst logical; variance stabilizing transformation. By default, the
#' function uses a regularized log transformation on the data set, however, this
#' will not suit all experimental designs.
#' 
#' @param labels logical; include sample name labels on PCA. Default 
#' `labels=TRUE`
#' 
#' @param boxed logical; add a box around each sample name label. Default 
#' `boxed=TRUE`
#' 
#' @param legend.title character; title for legend key. Default
#' `legend.title = "Conditions"`
#' 
#' @param title character; title for plot. 
#' 
#' @param size.ratio numeric; set plot ratio, broadens axis dimensions by ratio.
#' Default `size.ratio=2`, double the plot dimension. 
#'
#'@param colours character; vector of HEX colour codes. Must match the number of 
#'conditions. 
#'
#'@param point.shape logical; set whether the point shapes should be different
#'for each condition. 
#'
#'@param ggplot.theme character; state the `ggplot2` theme (without () 
#'brackets). For example, `ggplot.theme=ggplot2::theme_classic`.
#' 
#'@param legend.position character; the position of legends 
#'("none", "left", "right", "bottom", "top", or two-element numeric vector)
#'
#' @param legend.direction character; layout of items in legends
#' ("horizontal" or "vertical")
#' 
#' @param label.box.padding numeric; Amount of padding around bounding box,
#'  as a unit or number. Defaults to 1. 
#'  
#' @return A PCA plot to show sample distance.
#'
#' @details This function uses the `DESeq2` package to organise and plot the
#' data. It organises the data into a DESeqDataSet which undergoes 
#' log-transformation where the results are used to undertake the PCA analysis. 
#' The results are plotted against the principal  components 1 and 2.
#'
#' In special conditions, regularized log transformation will not suit
#' the experimental design. For example, an experimental design without
#' replicates. In this instance, it is preferable to change the default setting
#' and switch to a variance stabilizing transformation method
#' (\code{`vst=TRUE`}).
#'
#'
#' @examples
#' data("sRNA_data")
#'
#' groups <- c("Heterograft", "Heterograft", "Heterograft",
#'             "Selfgraft", "Selfgraft", "Selfgraft")
#'             
#'             
#' p <-  plotSamplePCA(data = sRNA_data, group = groups)
#'
#' plot(p)
#'
#'
#' @export
#' @importFrom dplyr select
#' @importFrom DESeq2 DESeqDataSetFromMatrix
#' @importFrom SimDesign quiet
#' @importFrom stats relevel
#' @importFrom DESeq2 estimateSizeFactors
#' @importFrom DESeq2 rlog
#' @importFrom DESeq2 plotPCA
#' @importFrom ggrepel geom_label_repel
#' @importFrom ggplot2 aes
#' @importFrom ggplot2 labs
#' @importFrom ggplot2 xlab
#' @importFrom ggplot2 ylab
#' @importFrom ggplot2 coord_fixed
#' @importFrom ggrepel geom_text_repel
#' @importFrom ggplot2 ggplot
#' @importFrom ggplot2 geom_point
#' @importFrom ggplot2 scale_color_manual
plotSamplePCA <- function(data, group, vst = FALSE, labels = TRUE, boxed = TRUE,
                          legend.title = "Conditions", size.ratio = 2, 
                          colours = NULL, point.shape = TRUE, 
                          ggplot.theme = NULL, label.box.padding = 1, 
                          title = "PCA plot", 
                          legend.position = "top", 
                          legend.direction = "horizontal"){
  if (base::missing(data) || !base::inherits(data, c("data.frame"))) {
    stop("data must be an object of class data.frame containing raw count data")
  }
  if (base::missing(group) || !base::inherits(group, c("character"))) {
    stop("group must be an object of class character vector containing the 
          experimental condition (Treatment vs. Control)")
  }
  data <- data %>% dplyr::select(tidyselect::starts_with("Count_"))
  # use DESeq to organise the data.
  column.data <- data.frame(conditions=as.factor(group))
  base::rownames(column.data) <- base::colnames(data)
  count.data.set <- SimDesign::quiet(DESeq2::DESeqDataSetFromMatrix(
    countData=data,colData=column.data,design= ~conditions))
  count.data.set$conditions <- stats::relevel(count.data.set$conditions,
                                              group[1])
  
  dds <- DESeq2::estimateSizeFactors(count.data.set)
  
  # log transform the data.
  
  if(vst ==TRUE){
    message("Transforming the count data with a variance stabilizing 
transformation...")
    rld1 <- DESeq2::varianceStabilizingTransformation(dds, blind = TRUE)
    # log transform the data.
  } else
    if(vst == FALSE) {
      message("Transforming the count data to the log2 scale...")
      rld1 <- DESeq2::rlog(dds, blind = TRUE) # log transform the data.
    }
  
  # use the DEseq plot pca function, store in an object.
  pca <- DESeq2::plotPCA(rld1, returnData = TRUE, intgroup = "conditions")
  colnames(pca)[colnames(pca) == 'conditions'] <- 'Conditions'
  rownames(pca) <- gsub("^Count_", "", rownames(pca))
  pca$name <- gsub("^Count_", "",  pca$name)
  percentVar <- round(100 * attr(pca, "percentVar"))
  
  message("---Organising principal component analysis")
  if(labels == TRUE){
    if(boxed == TRUE){
      X <- ggplot2::ggplot(pca, ggplot2::aes(PC1, PC2, color=Conditions)) +
        {if(point.shape) ggplot2::geom_point(size=3, ggplot2::aes(
          shape = Conditions))}+
        {if(point.shape == FALSE) ggplot2::geom_point(size=3)}+
        ggplot2::xlab(paste0("PC1: ",percentVar[1],"% variance")) +
        ggplot2::ylab(paste0("PC2: ",percentVar[2],"% variance")) + 
        {if(!is.null(colours)) ggplot2::scale_color_manual(values=colours)}+ 
        ggplot2::coord_fixed()+
        ggrepel::geom_label_repel(data = pca, ggplot2::aes(label = name), 
                                  show.legend = FALSE, box.padding = label.box.padding)+
        ggplot2::labs(color = legend.title, title = title) + 
        ggplot2::coord_fixed(ratio = size.ratio)+
        {if(!is.null(ggplot.theme)) ggplot.theme() }+
        ggplot2::theme(legend.position = legend.position,
              legend.justification='left',
              legend.direction=legend.direction,
              legend.text = ggplot2::element_text(size=12),
              legend.title = ggplot2::element_text(size = 11, face = "bold"),
              axis.text.x = ggplot2::element_text(colour = "black", size = 13,face = "bold", margin = ggplot2::margin(t = 10, b = 4)),
              axis.text.y = ggplot2::element_text(colour = "black", size = 13,face = "bold", margin = ggplot2::margin(r = 3)),
              axis.title.y = ggplot2::element_text( size = 16, face = "bold", margin = ggplot2::margin(r =8)),
              axis.title.x = ggplot2::element_text(size = 16, face = "bold"),
              plot.title = ggplot2::element_text(face="bold", size = 18),
              plot.subtitle = ggplot2::element_text(size = 14))
      
    } else
      X <- ggplot2::ggplot(pca, ggplot2::aes(PC1, PC2, color=Conditions)) +
        {if(point.shape) ggplot2::geom_point(size=3, ggplot2::aes(
          shape =Conditions))}+
        {if(point.shape == FALSE) ggplot2::geom_point(size=3)}+
        ggplot2::xlab(paste0("PC1: ",percentVar[1],"% variance")) +
        ggplot2::ylab(paste0("PC2: ",percentVar[2],"% variance")) + 
        {if(!is.null(colours)) ggplot2::scale_color_manual(values=colours)}+ 
        ggrepel::geom_label_repel(data = pca, ggplot2::aes(label = name), 
                                  show.legend = FALSE, box.padding = label.box.padding)+
        ggplot2::labs(color = legend.title, title = title) + 
        suppressMessages(ggplot2::coord_fixed(ratio = size.ratio))+
        {if(!is.null(ggplot.theme)) ggplot.theme() }+
        ggplot2::theme(legend.position = legend.position,
              legend.justification='left',
              legend.direction=legend.direction,
              legend.text = ggplot2::element_text(size=12),
              legend.title = ggplot2::element_text(size = 11, face = "bold"),
              axis.text.x = ggplot2::element_text(colour = "black", size = 13,face = "bold", margin = ggplot2::margin(t = 10, b = 4)),
              axis.text.y = ggplot2::element_text(colour = "black", size = 13,face = "bold", margin = ggplot2::margin(r = 3)),
              axis.title.y = ggplot2::element_text( size = 16, face = "bold", margin = ggplot2::margin(r =8)),
              axis.title.x = ggplot2::element_text(size = 16, face = "bold"),
              plot.title = ggplot2::element_text(face="bold", size = 18),
              plot.subtitle = ggplot2::element_text(size = 14))
    
    
  } else {
    X <- ggplot2::ggplot(pca, ggplot2::aes(PC1, PC2, color=Conditions)) +
      {if(point.shape) ggplot2::geom_point(size=3, ggplot2::aes(
        shape = Conditions))}+
      {if(point.shape == FALSE) ggplot2::geom_point(size=3)}+
      ggplot2::xlab(paste0("PC1: ",percentVar[1],"% variance")) +
      ggplot2::ylab(paste0("PC2: ",percentVar[2],"% variance")) + 
      {if(!is.null(colours)) ggplot2::scale_color_manual(values=colours)}+ 
      ggplot2::labs(color = legend.title, title = title) + 
      ggplot2::coord_fixed(ratio = size.ratio)+
      {if(!is.null(ggplot.theme)) ggplot.theme() }+
      ggplot2::theme(legend.position = legend.position,
            legend.justification='left',
            legend.direction=legend.direction,
            legend.text = ggplot2::element_text(size=12),
            legend.title = ggplot2::element_text(size = 11, face = "bold"),
            axis.text.x = ggplot2::element_text(colour = "black", size = 13,face = "bold", margin = ggplot2::margin(t = 10, b = 4)),
            axis.text.y = ggplot2::element_text(colour = "black", size = 13,face = "bold", margin = ggplot2::margin(r = 3)),
            axis.title.y = ggplot2::element_text( size = 16, face = "bold", margin = ggplot2::margin(r =8)),
            axis.title.x = ggplot2::element_text(size = 16, face = "bold"),
            plot.title = ggplot2::element_text(face="bold", size = 18),
            plot.subtitle = ggplot2::element_text(size = 14))
  }
  return(X)
}
