#' draw an oncoplot
#' @description takes output generated by read.maf and draws an oncoplot
#'
#' @details
#' Takes maf file as input and plots it as a matrix. Any desired clincal features can be added at the bottom of the oncoplot by providing \code{clinicalFeatures}.
#' Oncoplot can be sorted either by mutations or by clinicalFeatures using arguments \code{sortByMutation} and \code{sortByAnnotation} respectively.
#'
#'
#' @param maf an \code{\link{MAF}} object generated by \code{\link{read.maf}}
#' @param top how many top genes to be drawn. defaults to 20.
#' @param genes Just draw oncoplot for these genes. Default NULL.
#' @param mutsig Mutsig resuts if availbale. Usually file named sig_genes.txt If provided plots significant genes and correpsonding Q-values as side row-bar. Default NULL.
#' @param mutsigQval Q-value to choose significant genes from mutsig results. Default 0.1
#' @param drawRowBar logical plots barplot for each gene. Default \code{TRUE}.
#' @param drawColBar logical plots barplot for each sample. Default \code{TRUE}.
#' @param showTumorSampleBarcodes logical to include sample names.
#' @param clinicalFeatures columns names from `clinical.data` slot of \code{MAF} to be drawn in the plot. Dafault NULL.
#' @param annotationDat If MAF file was read without clinical data, provide a custom \code{data.frame} with a column containing Tumor_Sample_Barcodes along with rest of columns with annotations.
#' You can specify which columns to be drawn using `clinicalFeatures` argument.
#' @param genesToIgnore do not show these genes in Oncoplot. Default NULL.
#' @param annotationColor list of colors to use for `clinicalFeatures`. Must be a named list. Default NULL.
#' @param removeNonMutated Logical. If \code{TRUE} removes samples with no mutations in the oncoplot for better visualization. Default \code{TRUE}.
#' @param colors named vector of colors for each Variant_Classification.
#' @param sortByMutation Force sort matrix according mutations. Helpful in case of MAF was read along with copy number data. Default FALSE.
#' @param sortByAnnotation logical sort oncomatrix (samples) by provided `clinicalFeatures`. Sorts based on first `clinicalFeatures`.  Defaults to FALSE. column-sort
#' @param annotationOrder Manually specify order for annotations. Works only for first `clinicalFeatures`. Default NULL.
#' @param keepGeneOrder logical whether to keep order of given genes. Default FALSE, order according to mutation frequency
#' @param GeneOrderSort logical this is applicable when `keepGeneOrder` is TRUE. Default TRUE
#' @param sampleOrder Manually speify sample names for oncolplot ordering. Default NULL.
#' @param fontSize font size for gene names. Default 10.
#' @param SampleNamefontSize font size for sample names. Default 10
#' @param titleFontSize font size for title. Default 15
#' @param legendFontSize font size for legend. Default 12
#' @param annotationFontSize font size for annotations. Default 12
#' @param annotationTitleFontSize font size for annotation title. Default 12
#' @param writeMatrix writes character coded matrix used to generate the plot to an output file. This can be used as an input
#' for ComplexHeatmap \link[ComplexHeatmap]{oncoPrint} function if you wish to customize the plot.
#' @return None.
#' @examples
#' laml.maf <- system.file("extdata", "tcga_laml.maf.gz", package = "maftools")
#' laml <- read.maf(maf = laml.maf)
#' oncoplot(maf = laml, top = 3)
#' @import ComplexHeatmap
#' @import grid
#' @seealso \code{\link{oncostrip}}
#' @export


oncoplot = function (maf, top = 20, genes = NULL, mutsig = NULL, mutsigQval = 0.1, drawRowBar = TRUE, drawColBar = TRUE,
                     clinicalFeatures = NULL, annotationDat = NULL, annotationColor = NULL, genesToIgnore = NULL,
                     showTumorSampleBarcodes = FALSE, removeNonMutated = TRUE, colors = NULL,
                     sortByMutation = FALSE, sortByAnnotation = FALSE, annotationOrder = NULL, keepGeneOrder = FALSE,
                     GeneOrderSort = TRUE, sampleOrder = NULL, writeMatrix = FALSE, fontSize = 10, SampleNamefontSize = 10,
                     titleFontSize = 15, legendFontSize = 12, annotationFontSize = 12, annotationTitleFontSize = 12) {

  #set seed for consistancy.
  set.seed(seed = 1024)

  #-------------------------------------Preprocess matrix---------------------------------------------------

  if(!is.null(genes)){ #If user provides a gene list
    om = createOncoMatrix(m = maf, g = genes)
    numMat = om$numericMatrix
    mat_origin = om$oncoMatrix
  } else if(!is.null(mutsig)){ #If user provides significant gene table (e.g; mutsig results)

    if(as.logical(length(grep(pattern = 'gz$', x = mutsig, fixed = FALSE)))){
      #If system is Linux use fread, else use gz connection to read gz file.
      if(Sys.info()[['sysname']] == 'Windows'){
        mutsigResults.gz = gzfile(description = mutsig, open = 'r')
        suppressWarnings(ms <- data.table::as.data.table(read.csv(file = mutsigResults.gz, header = TRUE, sep = '\t', stringsAsFactors = FALSE, comment.char = '#')))
        close(mutsigResults.gz)
      } else{
        ms = suppressWarnings(data.table::fread(input = paste('zcat <', mutsig), sep = '\t', stringsAsFactors = FALSE, verbose = FALSE, data.table = TRUE, showProgress = TRUE, header = TRUE))
      }
    } else{
      ms = data.table::fread(input = mutsig, sep = '\t', stringsAsFactors = FALSE, header = TRUE)
    }

    ms$q = as.numeric(gsub(pattern = "^<", replacement = "", x = as.character(ms$q)))
    mach.epsi = .Machine$double.eps
    ms$q = ifelse(test = ms$q == 0, yes = mach.epsi, no = ms$q)
    ms[,FDR := -log10(as.numeric(as.character(q)))]
    ms.smg = ms[q < mutsigQval]
    genes = as.character(ms[q < mutsigQval, gene])

    om = createOncoMatrix(m = maf, g = genes)
    numMat = om$numericMatrix
    mat_origin = om$oncoMatrix

    #Check for any missing genes and ignore them if necessary
    if(length(genes[!genes %in% rownames(numMat)]) > 0){
      message('Following genes from MutSig results are not available in MAF:')
      print(genes[!genes %in% rownames(numMat)])
      message('Ignoring them.')
      genes = genes[genes %in% rownames(numMat)]
      ms.smg = ms.smg[gene %in% genes]
    }

    ms.smg = ms.smg[,.(gene, FDR)]
    ms.smg = data.frame(row.names = ms.smg$gene, FDR = ms.smg$FDR)
  }else { #If user does not provide gene list or MutSig results, draw TOP (default 20) genes

    genes = getGeneSummary(x = maf)[1:top, Hugo_Symbol]
    om = createOncoMatrix(m = maf, g = genes)
    numMat = om$numericMatrix
    mat_origin = om$oncoMatrix
  }

  #---remove genes from genesToIgnore if any
  if(!is.null(genesToIgnore)){
    numMat = numMat[!rownames(numMat) %in% genesToIgnore,]
    mat_origin = mat_origin[!rownames(mat_origin) %in% genesToIgnore,]
  }

  #If <2 samples stop !
  if(ncol(numMat) < 2){
    stop('Cannot create oncoplot for single sample. Minimum two sample required ! ')
  }

  #If <2 samples stop !
  if(nrow(numMat) < 2){
    stop('Cannot create oncoplot for single gene. Minimum two genes required ! ')
  }

  totSamps = as.numeric(maf@summary[3,summary])
  tsbs = levels(getSampleSummary(x = maf)[,Tumor_Sample_Barcode])

  #-----------------------

  #Annotations
  if(!is.null(clinicalFeatures)){
    if(!is.null(annotationDat)){
      data.table::setDF(annotationDat)
      if(length(clinicalFeatures[!clinicalFeatures %in% colnames(annotationDat)]) > 0){
        message('Following columns are missing from provided annotation data. Ignoring them..')
        print(clinicalFeatures[!clinicalFeatures %in% colnames(annotationDat)])
        clinicalFeatures = clinicalFeatures[clinicalFeatures %in% colnames(annotationDat)]
        if(length(clinicalFeatures) == 0){
          stop('Zero annotaions to add! Make sure at-least one of the provided clinicalFeatures are present in annotationDat')
        }
      }
      annotation = annotationDat[,c('Tumor_Sample_Barcode', clinicalFeatures)]
      annotation = data.frame(row.names = annotation$Tumor_Sample_Barcode ,annotation[,clinicalFeatures, drop = FALSE])
    } else{
      annotationDat = getClinicalData(x = maf)
      #data.table::setDF(annotationDat)
      if(length(clinicalFeatures[!clinicalFeatures %in% colnames(annotationDat)]) > 0){
        message('Following columns are missing from annotation slot of MAF. Ignoring them..')
        print(clinicalFeatures[!clinicalFeatures %in% colnames(annotationDat)])
        clinicalFeatures = clinicalFeatures[clinicalFeatures %in% colnames(annotationDat)]
        if(length(clinicalFeatures) == 0){
          message('Make sure at-least one of the values from provided clinicalFeatures are present in annotation slot of MAF. Here are available annotaions from MAF..')
          print(colnames(getClinicalData(maf)))
          stop('Zero annotaions to add! You can also provide custom annotations via annotationDat argument.')
        }
      }
      annotation = data.frame(row.names = annotationDat$Tumor_Sample_Barcode ,annotationDat[,clinicalFeatures, with = FALSE])
    }
  }

  #--Sort

  if(length(genes[!genes %in% rownames(numMat)]) > 0){
    message('Following genes from provided gene list are missing from MAF:')
    print(genes[!genes %in% rownames(numMat)])
    message('Ignoring them.')
    genes = genes[genes %in% rownames(numMat)]

    if(length(genes) < 1){
      stop('Only one gene left! At-least two genes required for plotting.')
    }
  }

  #By default oncomatrix excludes non-mutated samples. Add rest here if user requests
  if(!removeNonMutated){
    tsb.include = matrix(data = 0, nrow = length(genes), ncol = length(tsbs[!tsbs %in% colnames(numMat)]))
    colnames(tsb.include) =tsbs[!tsbs %in% colnames(numMat)]
    rownames(tsb.include) = rownames(numMat)
    numMat = cbind(numMat, tsb.include)
  }

  if(sortByMutation){
    numMat = sortByMutation(numMat = numMat, maf = maf)
  }

  if(sortByAnnotation){
    if(is.null(clinicalFeatures)){
      stop("Use argument `annotationCol` to provide at-least one of the annotations.")
    }
    numMat = sortByAnnotation(numMat = numMat, maf = maf, annotation, annoOrder = annotationOrder)
  }

  if(!is.null(sampleOrder)){
    numMat = numMat[,as.character(sampleOrder), drop = FALSE]
  }

  #Do the same thing for character matrix
  if(!removeNonMutated){
    tsb.include = matrix(data = '', nrow = length(genes), ncol = length(tsbs[!tsbs %in% colnames(mat_origin)]))
    colnames(tsb.include) = tsbs[!tsbs %in% colnames(mat_origin)]
    rownames(tsb.include) = rownames(mat_origin)
    mat_origin = cbind(mat_origin, tsb.include)
  }

  mat = mat_origin[rownames(numMat), , drop = FALSE]
  mat = mat[,colnames(numMat), drop = FALSE]

  #If user wannts to keep given gene order
  if(keepGeneOrder){
    if(GeneOrderSort){
      numMat = sortByGeneOrder(m = numMat, g = genes)
    }else{
      numMat = numMat[genes, , drop = FALSE]
    }
    mat = mat_origin[rownames(numMat), , drop = FALSE]
    mat = mat[,colnames(numMat), drop = FALSE]
  }

  #finally sort annotation data in same order as plot matrix
  if(!is.null(clinicalFeatures)){
    annotation = annotation[rownames(annotation) %in% colnames(mat),, drop = FALSE]
    annotation = annotation[colnames(mat), , drop = FALSE]
  }

  if (writeMatrix) {
    write.table(mat, "onco_matrix.txt", sep = "\t", quote = FALSE)
  }

  #New version of complexheatmap complains about '' , replacing them with random string xxx
  mat[mat == ''] = 'xxx'

  if(removeNonMutated){
    #mutSamples = length(unique(unlist(genesToBarcodes(maf = maf, genes = rownames(mat), justNames = TRUE))))
    altStat = paste0("Altered in ", ncol(mat), " (", round(ncol(mat)/totSamps, digits = 4)*100, "%) of ", totSamps, " samples.")
  }else{
    mutSamples = length(unique(unlist(genesToBarcodes(maf = maf, genes = rownames(mat), justNames = TRUE))))
    altStat = paste0("Altered in ", mutSamples, " (", round(mutSamples/totSamps, digits = 4)*100, "%) of ", totSamps, " samples.")
  }

  #---------------------------------------Colors and vcs-------------------------------------------------

  #hard coded colors for variant classification if user doesnt provide any
  if(is.null(colors)){
    col = c(RColorBrewer::brewer.pal(12,name = "Paired"), RColorBrewer::brewer.pal(11,name = "Spectral")[1:3],'black', 'violet', 'royalblue')
    names(col) = names = c('Nonstop_Mutation','Frame_Shift_Del','IGR','Missense_Mutation','Silent','Nonsense_Mutation',
                           'RNA','Splice_Site','Intron','Frame_Shift_Ins','Nonstop_Mutation','In_Frame_Del','ITD','In_Frame_Ins',
                           'Translation_Start_Site',"Multi_Hit", 'Amp', 'Del')
  }else{
    col = colors
  }

  bg = "#CCCCCC" #Default gray background
  col = c(col, 'xxx' = bg)

  #Variant classes available in matrix
  print(col)
  variant.classes = unique(unlist(as.list(apply(mat_origin, 2, unique))))
  variant.classes = unique(unlist(strsplit(x = variant.classes, split = ';', fixed = TRUE)))
  variant.classes = variant.classes[!variant.classes %in% c('xxx')]

  #type_col = structure(col[variant.classes], names = names(col[variant.classes]))
  #type_col = type_col[!is.na(type_col)]
  type_col = col


  type_name = structure(variant.classes, names = variant.classes)

  variant.classes = variant.classes[!variant.classes %in% c('Amp', 'Del')]

  #Variant classes available in plot matrix (We want to color code all vc's in colbar but only use those
  #in plot matrix for legend)
  vc.mat = unique(unlist(as.list(apply(mat, 2, unique))))
  vc.mat = unique(unlist(strsplit(x = vc.mat, split = ';', fixed = TRUE)))
  vc.mat = vc.mat[!vc.mat %in% c('xxx')]
  vc.type_name = structure(vc.mat, names = vc.mat)

  vc.type_col = structure(col[vc.mat], names = names(col[vc.mat]))
  vc.type_col = vc.type_col[!is.na(vc.type_col)]

  #Bottom annotations
  if(!is.null(clinicalFeatures)){
    if(!is.null(annotationColor)){
      bot.anno = ComplexHeatmap::HeatmapAnnotation(df = annotation, col = annotationColor, annotation_legend_param = list(title_gp = gpar(fontsize = annotationTitleFontSize, fontface = "bold"),
                                                   labels_gp = gpar(fontsize = annotationFontSize, fontface = "bold")))
    }else{
      bot.anno = ComplexHeatmap::HeatmapAnnotation(annotation, annotation_legend_param = list(title_gp = gpar(fontsize = annotationTitleFontSize, fontface = "bold"),
                                                   labels_gp = gpar(fontsize = annotationFontSize, fontface = "bold")))
    }
  }


  #------------------------------------functions to add %, rowbar and colbar----------------------------------------------------

  #------------------------------------------------------------------------------------------------------
  #Many thanks to Zuguang Gu (ComplexHeatmap) for letting me use the below code !
  #Modifed for maftools.
  #------------------------------------------------------------------------------------------------------

  ##This function adds percent rate
  # anno_pct = function(index){
  #   n = length(index)
  #   pct = paste0(round(apply(numMat[rownames(mat)[n],], 1, function(x) length(x[x != 0]))/as.numeric(maf@summary[3, summary]), digits = 2)*100, "%")
  #   grid::pushViewport(viewport(xscale = c(0, 1), yscale = c(0.5, n + 0.5)))
  #   grid::grid.text(pct, x = 1, y = seq_along(index), default.units = "native",
  #                   just = "right", gp = grid::gpar(fontsize = fontSize))
  #   grid::upViewport()
  # }


  anno_pct = function(index) {
    n = length(index)
    pct = apply(numMat[rev(index),], 1, function(x) length(x[x != 0]))/totSamps * 100
    pct = paste0(round(pct), "%")
    grid::pushViewport(viewport(xscale = c(0, 1), yscale = c(0.5, n + 0.5)))
    grid::grid.text(pct, x = 1, y = seq_along(index), default.units = "native",
                    just = "right", gp = grid::gpar(fontsize = fontSize, fontface = "bold"))
    grid::upViewport()
  }

  ha_pct = ComplexHeatmap::HeatmapAnnotation(pct = anno_pct,
                                             width = grid::grobWidth(grid::textGrob("100%", gp = grid::gpar(fontsize = 10))), which = "row")

  ##This function adds rowbar
  if(!is.null(mutsig)){
    anno_row_bar = function(index){
      n = length(index)

      max_count = max(as.numeric(as.character(ms.smg$FDR)))
      tb = rev(as.list(ms.smg$FDR))
      grid::pushViewport(grid::viewport(xscale = c(0, max_count * 1.1), yscale = c(0.5, n + 0.5)))
      for (i in seq_along(tb)) {
        if (length(tb[[i]])) {
          x = cumsum(tb[[i]])
          grid::grid.rect(x = x, i, width = tb[[i]], height = 0.8,
                          default.units = "native", just = "right",
                          gp = grid::gpar(col = NA, fill = "gray70"))
        }
      }
      breaks = grid::grid.pretty(c(0, max_count))
      grid::grid.xaxis(at = breaks, label = breaks, main = FALSE,
                       gp = grid::gpar(fontsize = 10))
      grid::upViewport()
    }
  }else{
    anno_row_bar = function(index) {
      n = length(index)

      tb = list()
      for(i in nrow(mat):1){
        x = mat[i,]
        x = x[x != '']
        x = x[x != 'xxx']
        x = unlist(strsplit(x, ";"))
        x = sort(x)
        tb[[i]] = table(x)
      }
      tb = rev(tb)

      max_count = max(sapply(tb, sum))
      grid::pushViewport(grid::viewport(xscale = c(0, max_count * 1.1), yscale = c(0.5, n + 0.5)))
      for (i in seq_along(tb)) {
        if (length(tb[[i]])) {
          x = cumsum(tb[[i]])
          grid::grid.rect(x = x, i, width = tb[[i]], height = 0.8,
                          default.units = "native", just = "right",
                          gp = grid::gpar(col = NA, fill = type_col[names(tb[[i]])]))
        }
      }
      breaks = grid::grid.pretty(c(0, max_count))
      grid::grid.xaxis(at = breaks, label = breaks, main = FALSE,
                       gp = grid::gpar(fontsize = 10))
      grid::upViewport()
    }
  }


  ha_row_bar = ComplexHeatmap::HeatmapAnnotation(row_bar = anno_row_bar,
                                                 width = grid::unit(4, "cm"), which = "row")

  ##This function adds columnbar
  anno_column_bar = function(index) {
    n = length(index)
    ss = getSampleSummary(x = maf)
    tb = ss[Tumor_Sample_Barcode %in% colnames(mat)]
    tb = tb[,colnames(tb)[!colnames(tb) %in% c('total', 'Amp', 'Del', 'CNV_total')], with = FALSE]
    tb = split(tb, as.factor(as.character(tb$Tumor_Sample_Barcode)))
    tb = lapply(X = tb, function(x) unlist(x)[-1])
    tb = tb[colnames(mat)]

    max_count = max(sapply(tb, sum))

    grid::pushViewport(grid::viewport(yscale = c(0, max_count * 1.1),
                                      xscale = c(0.5, n + 0.5)))
    for (i in seq_along(tb)) {
      print(tb[[i]])
      if (length(tb[[i]])) {
        y = cumsum(tb[[i]])
        #print(y)
        grid::grid.rect(i, y, height = tb[[i]], width = 0.8,
                        default.units = "native", just = "top",
                        gp = grid::gpar(col = NA, fill = type_col[names(tb[[i]])]))
        print(type_col[names(tb[[i]])])
      }
    }
    breaks = grid::grid.pretty(c(0, max_count))
    grid::grid.yaxis(at = breaks, label = breaks, gp = grid::gpar(fontsize = 10))
    grid::upViewport()
  }

  ha_column_bar = ComplexHeatmap::HeatmapAnnotation(column_bar = anno_column_bar, which = "column")

  ##Following two funcs add grids
  add_oncoprint = function(type, x, y, width, height) {
    grid::grid.rect(x, y, width - unit(0.5, "mm"),
                    height - grid::unit(1, "mm"), gp = grid::gpar(col = NA, fill = bg))

    for (i in 1:length(variant.classes)) {
      if (any(type %in% variant.classes[i])) {
        grid::grid.rect(x, y, width - unit(0.5, "mm"), height -
                          grid::unit(1, "mm"), gp = grid::gpar(col = NA, fill = type_col[variant.classes[i]]))
      } else if (any(type %in% 'Amp')) {
        grid::grid.rect(x, y, width - unit(0.5, "mm"), height -
                          grid::unit(1, "mm"), gp = grid::gpar(col = NA, fill = bg))
        grid::grid.rect(x, y, width - unit(0.5, "mm"), height -
                          unit(15, 'mm'), gp = grid::gpar(col = NA, fill = type_col['Amp']))
      } else if (any(type %in% 'Del')) {
        grid::grid.rect(x, y, width - unit(0.5, "mm"), height -
                          grid::unit(1, "mm"), gp = grid::gpar(col = NA, fill = bg))
        grid::grid.rect(x, y, width - unit(0.5, "mm"), height - grid::unit(15, "mm")
                        , gp = grid::gpar(col = NA, fill = type_col['Del']))
      }
    }
  }

  add_oncoprint2 = function(type, x, y, width, height) {
    for (i in 1:length(variant.classes)) {
      if (any(type %in% variant.classes[i])) {
        grid::grid.rect(x, y, width - unit(0.5, "mm"), height -
                          grid::unit(1, "mm"), gp = grid::gpar(col = NA, fill = type_col[variant.classes[i]]))
      } else if (any(type %in% 'Amp')) {
        grid::grid.rect(x, y, width - unit(0.5, "mm"), height -
                          unit(15, 'mm'), gp = grid::gpar(col = NA, fill = type_col['Amp']))
      } else if (any(type %in% 'Del')) {

        grid::grid.rect(x, y, width - unit(0.5, "mm"), height - grid::unit(15, "mm")
                        , gp = grid::gpar(col = NA, fill = type_col['Del']))
      }
    }
  }

  #This is the main cel function which is passed to ComplexHeatmap::Hetamap()
  celFun = function(j, i, x, y, width, height, fill) {
    type = mat[i, j]
    if(type != 'xxx'){
      typeList = sort(unlist(strsplit(x = as.character(type), split = ';')), decreasing = TRUE)
      if(length(typeList) > 1){
        for(i in 1:length(typeList)){
          add_oncoprint2(typeList[i], x, y, width, height)
        }
      }else{
        for(i in 1:length(typeList)){
          add_oncoprint(typeList[i], x, y, width, height)
        }
      }

    }else{
      add_oncoprint(type, x, y, width, height)
    }
  }


  #----------------------------------------------------------------------------------------


  if(drawColBar){
    if(is.null(clinicalFeatures)){

      ht = ComplexHeatmap::Heatmap(mat, na_col = bg,rect_gp = grid::gpar(type = "none"), cell_fun = celFun,
                                   row_names_gp = grid::gpar(fontsize = fontSize, fontface = "bold"), show_column_names = showTumorSampleBarcodes,
                                   show_heatmap_legend = FALSE, top_annotation = ha_column_bar,
                                   top_annotation_height = grid::unit(2, "cm"),
                                   column_title_gp = grid::gpar(fontsize = titleFontSize, fontface = "bold"), column_title = altStat)
    } else{

      ht = ComplexHeatmap::Heatmap(mat, na_col = bg,rect_gp = grid::gpar(type = "none"), cell_fun = celFun,
                                   row_names_gp = grid::gpar(fontsize = fontSize, fontface = "bold"), show_column_names = showTumorSampleBarcodes,
                                   show_heatmap_legend = FALSE, top_annotation = ha_column_bar,
                                   top_annotation_height = grid::unit(2, "cm"), bottom_annotation = bot.anno,
                                   column_title_gp = grid::gpar(fontsize = titleFontSize, fontface = "bold"), column_title = altStat)
    }

  } else{

    if(is.null(clinicalFeatures)){

      ht = ComplexHeatmap::Heatmap(mat, na_col = bg, rect_gp = grid::gpar(type = "none"), cell_fun = celFun,
                                   row_names_gp = grid::gpar(fontsize = fontSize, fontface = "bold"), show_column_names = showTumorSampleBarcodes,
                                   show_heatmap_legend = FALSE,
                                   column_title_gp = grid::gpar(fontsize = titleFontSize, fontface = "bold"), column_title = altStat)
    }else{
      ht = ComplexHeatmap::Heatmap(mat, na_col = bg, rect_gp = grid::gpar(type = "none"), cell_fun = celFun,
                                   row_names_gp = grid::gpar(fontsize = fontSize, fontface = "bold"), show_column_names = showTumorSampleBarcodes,
                                   show_heatmap_legend = FALSE, bottom_annotation = bot.anno,
                                   column_title_gp = grid::gpar(fontsize = titleFontSize, fontface = "bold"), column_title = altStat)
    }
  }

  ha_pct = ComplexHeatmap::HeatmapAnnotation(pct = anno_pct,
                                             width = grid::grobWidth(grid::textGrob("100%", gp = grid::gpar(fontsize = 10, fontface = "bold"))),
                                             which = "row")
  ht_list = ha_pct + ht


  if(drawRowBar){
    ht_list =  ht_list + ha_row_bar
  }

  legend = grid::legendGrob(labels = vc.type_name[names(vc.type_col)],  pch = 15, gp = grid::gpar(col = vc.type_col, fontsize = legendFontSize, fontface = "bold"), nrow = 3)

  suppressWarnings( ComplexHeatmap::draw(ht_list, newpage = FALSE, annotation_legend_side = "bottom", annotation_legend_list = list(legend)) )
}
