#' get_channels
#' 
#' Get channel names for an array of markers, given a flowFrame 
#' 
#' @param ff      The flowFrame of interest
#' @param markers Vector with markers or channels of interest
#'                  
#' @return Corresponding channel names
#'
#' @seealso \code{\link{get_markers}}
#'
#' @examples
#' 
#'    # Read the flowFrame
#'    fileName <- system.file("extdata", "68983.fcs", package="FlowSOM")
#'    ff <- flowCore::read.FCS(fileName)
#'    GetChannels(ff, c("FSC-A", "CD3", "FITC-A"))
#'    GetMarkers(ff, c("FSC-A", "CD3", "FITC-A"))
#'
#' @export
get_channels <- function(ff, markers) { 
  .Deprecated("GetChannels")
  channelnames <- GetChannels(ff, markers)
  return(channelnames)
}

#' get_markers
#' 
#' Get marker names, given a flowFrame. As available in "desc". If this is NA,
#' defaults to channel name.
#' 
#' @param ff      The flowFrame of interest
#' @param markers Vector with markers or channels of interest
#'                  
#' @return Corresponding marker names
#'
#' @seealso \code{\link{get_channels}}
#'
#' @examples
#' 
#'    # Read the flowFrame
#'    fileName <- system.file("extdata", "68983.fcs", package="FlowSOM")
#'    ff <- flowCore::read.FCS(fileName)
#'    GetChannels(ff, c("FSC-A", "CD3", "FITC-A"))
#'    GetMarkers(ff, c("FSC-A", "CD3", "FITC-A"))
#'
#' @export
get_markers <- function(ff, markers) {
  .Deprecated("GetMarkers")
  markernames <- GetMarkers(ff, markers)
  return(markernames)
}

#' Get MFI values for all clusters
#'
#' @param  fsom             FlowSOM object as generated by the FlowSOM function
#'                          or the BuildSOM function
#' @param  colsUsed         logical. Should report only the columns used to 
#'                          build the SOM. Default = FALSE.
#' @param  prettyColnames   logical. Should report pretty column names instead
#'                          of standard column names. Default = FALSE.
#'                          
#' @return Matrix with median values for each marker
#'
#' @examples 
#' fileName <- system.file("extdata", "68983.fcs", package="FlowSOM")
#' flowSOM.res <- FlowSOM(fileName, compensate=TRUE,transform=TRUE,
#'                       scale=TRUE,colsToUse=c(9,12,14:18),nClus=10)
#' mfis <- GetClusterMFIs(flowSOM.res)
#' @export 
GetMFIs <- function(fsom, colsUsed = FALSE, prettyColnames = FALSE){
  .Deprecated("GetClusterMFIs")
  MFIs <- GetClusterMFIs(fsom, colsUsed, prettyColnames)
  return(MFIs)
}

#' Get CV values for all clusters
#'
#' @param  fsom             FlowSOM object as generated by the FlowSOM function
#'                          or the BuildSOM function
#'                          
#' @return Matrix with coefficient of variation values for each marker
#' 
#' fileName <- system.file("extdata", "68983.fcs", package="FlowSOM")
#' flowSOM.res <- FlowSOM(fileName, compensate=TRUE,transform=TRUE,
#'                       scale=TRUE,colsToUse=c(9,12,14:18),nClus=10)
#' cvs <- GetClusterCVs(flowSOM.res)
#'
#' @export
GetCVs <- function(fsom){
  .Deprecated("GetClusterCVs")
  results <- GetClusterCVs(fsom)
  return(results)
}


#' UpdateNodeSize
#'
#' Update nodesize of FlowSOM object
#' 
#' Add size property to the graph based on cellcount for each node
#' 
#' @param fsom     FlowSOM object, as generated by \code{\link{BuildMST}}
#' @param count    Absolute cell count of the sample
#' @param reset    Logical. If \code{TRUE}, all nodes get the same size
#' @param transform Transformation function. Use e.g. square root to let counts
#'                 correspond with area of node instead of radius
#' @param maxNodeSize Maximum node size after rescaling. Default: 15
#' @param shift    Shift of the counts, defaults to 0
#' @param scale    Scaling of the counts, defaults to the maximum of the value
#'                 minus the shift. With shift and scale set as default, the 
#'                 largest node will be maxNodeSize and an empty node will have
#'                 size 0
#' 
#' @return Updated FlowSOM object
#' @seealso \code{\link{BuildMST}}
#' 
#' @examples 
#' # Read from file, build self-organizing map and minimal spanning tree
#' fileName <- system.file("extdata", "68983.fcs", package="FlowSOM")
#' flowSOM.res <- ReadInput(fileName, compensate=TRUE,transform=TRUE,
#'                         scale=TRUE)
#' flowSOM.res <- BuildSOM(flowSOM.res,colsToUse=c(9,12,14:18))
#' flowSOM.res <- BuildMST(flowSOM.res)
#'
#' # Give all nodes same size
#' PlotStars(flowSOM.res, equalNodeSize = TRUE)
#'
#' # Node sizes relative to amount of cells assigned to the node
#' PlotStars(flowSOM.res)
#' 
#' @export
UpdateNodeSize <- function(fsom, count = NULL, reset=FALSE, transform=sqrt,
                           maxNodeSize = 15,
                           shift = 0, scale = NULL){
  .Deprecated("the equalNodeSize and maxNodeSize parameters in the plot functions")
  if(reset){
    fsom$MST$size <- rep(maxNodeSize, nrow(fsom$map$grid))
  } else {
    t <- rep(0, fsom$map$nNodes)
    names(t) <- as.character(seq_len(fsom$map$nNodes))
    t_tmp <- table(fsom$map$mapping[, 1]) / nrow(fsom$map$mapping)
    t[names(t_tmp)] <- t_tmp
    
    if(!is.null(count)){
      t <- (t/sum(t)) * count
    }
    
    if(!is.null(transform)){
      t <- transform(t)
    }
    
    if(is.null(shift)) shift <- min(t)
    if(is.null(scale)) scale <- max(t - shift)
    rescaled <- maxNodeSize * (t - shift)/scale
    rescaled[rescaled == 0] <- 0.0001
    fsom$MST$size <- rescaled   
  }
  fsom
}

#' PlotClusters2D 
#' 
#' Plot nodes on scatter plot
#' 
#' Plot a 2D scatter plot. All cells of fsom$data are plotted in
#' black, and those of the selected nodes are plotted in red.
#' The nodes in the grid are indexed starting from the left bottom,
#' first going right, then up. E.g. In a 10x10 grid, the node at
#' top left will have index 91.
#'  
#' @param fsom    FlowSOM object, as generated by \code{\link{BuildMST}}
#' @param marker1 Marker to plot on the x-axis
#' @param marker2 Marker to plot on the y-axis
#' @param nodes   Nodes of which the cells should be plotted in red
#' @param main    Title of the plot
#' @param col     Colors for all the cells in the selected nodes (ordered array)
#' @param maxBgPoints Maximum number of background points to plot
#' @param pchBackground Character to use for background cells
#' @param pchCluster Character to use for cells in cluster
#' @param xlab    Label for the x axis
#' @param ylab    Label for the y axis
#' @param xlim    Limits for the x axis
#' @param ylim    Limits for the y axis
#' @param ...     Other parameters to pass on to plot
#'
#' @return Nothing is returned. A plot is drawn in which all cells are plotted
#'         in black and the cells of the selected nodes in red.
#' @seealso \code{\link{PlotNumbers}}, \code{\link{PlotCenters}},
#'          \code{\link{BuildMST}}
#' 
#' @examples
#' 
#'    ## Deprecated - use Plot2DScatters instead ##
#'  
#'    # Read from file, build self-organizing map and minimal spanning tree
#'    fileName <- system.file("extdata", "68983.fcs", package = "FlowSOM")
#'    flowSOM.res <- ReadInput(fileName, compensate = TRUE, transform = TRUE,
#'                             scale = TRUE)
#'    flowSOM.res <- BuildSOM(flowSOM.res, colsToUse = c(9, 12, 14:18))
#'   flowSOM.res <- BuildMST(flowSOM.res)
#'    
#'    # Plot cells
#'    \dontrun{
#'    Plot2DScatters(flowSOM.res, c(1, 2), clusters = 91)
#'    }
#'
#' @export
PlotClusters2D <- function(fsom, marker1, marker2, nodes, 
                           col = "#FF0000", maxBgPoints = 10000,
                           pchBackground = ".",
                           pchCluster = ".",
                           main = "",
                           xlab = fsom$prettyColnames[marker1],
                           ylab = fsom$prettyColnames[marker2],
                           xlim = c(min(fsom$data[, marker1]),
                                    max(fsom$data[, marker1])),
                           ylim = c(min(fsom$data[, marker2]),
                                    max(fsom$data[, marker2])),
                           ...){
  .Deprecated("Plot2DScatters")
  marker1 <- GetChannels(fsom, marker1)
  marker2 <- GetChannels(fsom, marker2)
  if(!is.null(maxBgPoints)){
    background <- sample(seq_len(nrow(fsom$data)),
                         min(maxBgPoints, nrow(fsom$data)))
  } else{
    background <- seq_len(nrow(fsom$data))
  }
  graphics::plot(fsom$data[background, c(marker1, marker2)], 
                 pch = pchBackground, col = "#000000AA",
                 main = main, xlab = xlab, ylab = ylab,
                 xlim = xlim, ylim = ylim,
                 ...)
  graphics::points(fsom$data[GetClusters(fsom) %in% nodes,
                             c(marker1, marker2)], 
                   pch = pchCluster, 
                   col = col)
  graphics::points(fsom$map$medianValues[nodes, marker1],
                   fsom$map$medianValues[nodes, marker2],
                   pch = "x", col = "blue")
  #cat(nodes, ": \n", table(m[GetClusters(fsom) %in% nodes]), "\n")
}

#' PlotOverview2D
#' 
#' Plot metaclusters on scatter plots
#' 
#' Write multiple 2D scatter plots to a png file. 
#' All cells of fsom$data are plotted in black, and those of the selected 
#' metaclusters are plotted in color.
#'  
#' @param fsom         FlowSOM object, as generated by \code{\link{FlowSOM}}.
#'                     If using a FlowSOM object as generated by 
#'                     \code{\link{BuildMST}}, it needs to be wrapped in a list,
#'                     list(FlowSOM = fsom, metaclustering = metaclustering).
#' @param markerlist   List in which each element is a pair of marker names
#' @param metaclusters Metaclusters of interest
#' @param colors       Named vector with color value for each metacluster. 
#'                     If NULL (default) colorbrewer "paired" is interpolated
#' @param ff           flowFrame to use as reference for the marker names
#' @param ...     Other parameters to pass on to PlotClusters2D
#'
#' @return Nothing is returned, but a plot is drawn for every markerpair and
#'         every metacluster. The individual cells are colored, and the 
#'         center of each FlowSOM cluster is indicated with a blue cross.
#' @seealso \code{\link{PlotClusters2D}}
#' 
#' @examples
#' 
#'    ## Deprecated - use Plot2DScatters instead ##
#' 
#'    # Read from file, build self-organizing map and minimal spanning tree
#'    fileName <- system.file("extdata", "68983.fcs", package = "FlowSOM")
#'    flowSOM.res <- FlowSOM(fileName, 
#'                           compensate = TRUE, transform = TRUE, scale = TRUE,
#'                           colsToUse = c(9, 12, 14:18),
#'                           nClus = 10,
#'                           seed = 1)
#'                           
#'    # Plot cells
#'    markers_of_interest = list(c("FSC-A", "SSC-A"),
#'                               c("CD3", "CD19"),
#'                               c("TCRb", "TCRyd"),
#'                               c("CD4", "CD8"))
#'    metaclusters_of_interest = 1:10
#'    
#'    # Recommended to write to png
#'    
#'    \dontrun{
#'      png("Markeroverview.png",
#'          width = 500 * length(markers_of_interest),
#'          height = 500 * length(metaclusters_of_interest))
#'      Plot2DScatters(flowSOM.res,
#'                     channelpairs = markers_of_interest,
#'                     metaclusters = metaclusters_of_interest)
#'      dev.off()
#'    }
#'
#' @export
PlotOverview2D <- function(fsom, 
                           markerlist, 
                           metaclusters,
                           colors = NULL,
                           ff,
                           ...){
  .Deprecated("Plot2DScatters")
  graphics::layout(matrix(seq_len(length(markerlist) * length(metaclusters)), 
                          nrow = length(metaclusters)))
  if(is.null(colors)){
    colors <- c("#A6CEE3", "#1F78B4", "#B2DF8A", "#33A02C", "#FB9A99", "#E31A1C", 
                "#FDBF6F", "#FF7F00", "#CAB2D6", "#6A3D9A", "#FFFF99", "#B15928")
    colors <- rep(colors, length.out = length(metaclusters))
    names(colors) <- as.character(metaclusters)
  }
  
  for(marker_pair in markerlist){
    for(metacluster in metaclusters){
      PlotClusters2D(fsom,
                     marker1 = marker_pair[1],
                     marker2 = marker_pair[2],
                     nodes = which(fsom$metaclustering == metacluster),
                     main = paste0("Metacluster ", metacluster),
                     col = colors[as.character(metacluster)],
                     ...)
    }
  }
  
  graphics::layout(1)
}

#' MetaclusterMFIs
#' 
#' Compute the median fluorescence intensities for the metaclusters
#'
#' @param fsom Result of calling the FlowSOM function
#' @return  Metacluster MFIs
#' @examples
#' fileName <- system.file("extdata", "68983.fcs", package="FlowSOM")
#' ff <- flowCore::read.FCS(fileName)
#' ff <- flowCore::compensate(ff,ff@@description$SPILL)
#' ff <- flowCore::transform(ff,
#'          flowCore::transformList(colnames(ff@@description$SPILL),
#'                                 flowCore::logicleTransform()))
#' flowSOM.res <- FlowSOM(ff,scale=TRUE,colsToUse=c(9,12,14:18),maxMeta=10)
#' mfis <- GetMetaclusterMFIs(flowSOM.res)
#' @export
MetaclusterMFIs <- function(fsom){
  .Deprecated("GetMetaclusterMFIs")
  MFIs <- GetMetaclusterMFIs(fsom)
  return(MFIs)
}

#' MetaclusterCVs
#' 
#' Compute the coefficient of variation for the metaclusters
#'
#' @param fsom Result of calling the FlowSOM function
#' @return  Metacluster CVs
#' @examples
#' fileName <- system.file("extdata", "68983.fcs", package="FlowSOM")
#' ff <- flowCore::read.FCS(fileName)
#' ff <- flowCore::compensate(ff,ff@@description$SPILL)
#' ff <- flowCore::transform(ff,
#'          flowCore::transformList(colnames(ff@@description$SPILL),
#'                                 flowCore::logicleTransform()))
#' flowSOM.res <- FlowSOM(ff,scale=TRUE,colsToUse=c(9,12,14:18), nClus=10)
#' cvs <- GetMetaclusterCVs(flowSOM.res)
#' @export
MetaclusterCVs <- function(fsom){
  .Deprecated("GetMetaclusterCVs")
  CVs <- GetMetaclusterCVs(fsom)
  return(CVs)
}

#' PlotGroups 
#' 
#' Plot differences between groups
#' 
#' Plot FlowSOM trees, where each node is represented by 
#' a star chart indicating mean marker values, the size of the node is relative
#' to the mean percentage of cells present in each
#'
#' @param fsom          FlowSOM object, as generated by \code{\link{BuildMST}}
#' @param groups        Groups result as generated by \code{\link{CountGroups}}
#' @param threshold     Relative difference in groups before the node is 
#'                      colored
#' @param pThreshold    Threshold on p-value from wilcox-test before the 
#'                      node is colored. If this is not NULL, threshold will 
#'                      be ignored.
#' @param ...           Additional arguments to pass to \code{\link{PlotFlowSOM}}
#'                          
#' @return A vector containing the labels assigned to the nodes for
#'         all groups except the first
#'         
#' @seealso \code{\link{PlotStars}},\code{\link{PlotVariable}},
#' \code{\link{PlotFlowSOM}},\code{\link{PlotLabels}},\code{\link{PlotNumbers}},
#' \code{\link{PlotMarker}},\code{\link{PlotPies}},\code{\link{QueryStarPlot}},
#' \code{\link{PlotSD}}
#' 
#' @examples
#' #Run FlowSOM
#' fileName <-  system.file("extdata", "68983.fcs", package="FlowSOM")
#' fsom <- FlowSOM(fileName, compensate = TRUE, transform = TRUE,
#'                       scale = TRUE, colsToUse = c(9,12,14:18), nClus = 10)
#' 
#' ff <- flowCore::read.FCS(fileName)
#' # Make an additional file without cluster 7 and double amount of cluster 5
#' selection <- c(which(GetClusters(fsom) %in% which(fsom$metaclustering != 7)),
#'                  which(GetClusters(fsom) %in% which(fsom$metaclustering == 5)))
#' ff_tmp <- ff[selection,]
#' flowCore::write.FCS(ff_tmp, file="ff_tmp.fcs")
#' 
#' # Compare only the file with the double amount of cluster 10
#' features <- GetFeatures(fsom, 
#'                         c(fileName, "ff_tmp.fcs"),
#'                         level = "clusters",
#'                         type = "percentages")
#' stats <- GroupStats(features$cluster_percentages,                     
#'                     groups = list("AllCells" = c(fileName),
#'                                   "Without_ydTcells" = c("ff_tmp.fcs")))
#'
#' fold_changes <- stats["fold changes", ]
#' fold_changes_label <- factor(ifelse(fold_changes < -1.5, 
#'                            "Underrepresented compared to Group 1",
#'                            ifelse(fold_changes > 1.5, 
#'                                   "Overrepresented compared to Group 1",
#'                                   "--")), 
#'                             levels = c("--", 
#'                                "Underrepresented compared to Group 1",
#'                                "Overrepresented compared to Group 1"))
#' fold_changes_label[is.na(fold_changes_label)] <- "--"                                   
#' gr_1 <- PlotStars(fsom, 
#'                   title = "All Cells", 
#'                   nodeSizes = stats["medians AllCells", ], 
#'                   list_insteadof_ggarrange = TRUE)
#' gr_2 <- PlotStars(fsom, title = "Group 2", 
#'                nodeSizes = stats["medians Without_ydTcells", ], 
#'                 backgroundValues = fold_changes_label,
#'                backgroundColors = c("white", "red", "blue"), 
#'                list_insteadof_ggarrange = TRUE)
#' p <- ggpubr::ggarrange(plotlist = c(list(gr_1$tree), gr_2),
#'                     heights = c(3, 1))
#' p                   
#'          
#' @importFrom grDevices colorRampPalette
#' 
#' @export
PlotGroups <- function(fsom, 
                       groups, 
                       threshold = NULL, 
                       pThreshold = 0.05,
                       ...){
  .Deprecated("GetFeatures and GroupStats")
  fsom <- UpdateFlowSOM(fsom)
  
  groupnames <- rownames(groups$means)
  annotation <- list()
  groupLevels <- c("--", 
                   paste0("Underexpressed compared to ", groupnames[1]), 
                   paste0("Overexpressed compared to ", groupnames[1]))
  for (group in groupnames[-1]) {
    if (!is.null(pThreshold) & is.null(threshold)) {
      values <- groups$pctgs
      pValues <- c()
      for (i in seq_len(ncol(values))) {
        test <- stats::wilcox.test(values[groups$groups %in% groupnames[1], i],
                                   values[groups$groups %in% group, i], 
                                   exact = FALSE)
        pValues <- c(pValues, test$p.value)
      }
      diff <- groups$means[group, ] - groups$means[groupnames[1], ]
      adjustedP <- stats::p.adjust(pValues, "BH")
      
      score <- 1 + (adjustedP < pThreshold) + (diff > 0 & adjustedP < pThreshold)
      annotation[[group]] <- factor(groupLevels[score], levels = groupLevels)
    } else if (is.null(pThreshold) & !is.null(threshold)) {
      diff <- groups$means[group, ] - groups$means[1, ]
      values <- (apply(groups$means[c(groupnames[1], group), ], 2, max) / 
                   apply(groups$means[c(groupnames[1], group), ], 2, min))
      annotation[[group]] <- factor(groupLevels
                                    [1 + (values > threshold) + 
                                        (diff > 0 & values > threshold)],
                                    levels = groupLevels)
    } else {
      stop("Please use only threshold or pThreshold, not both.")
    }
  }

  resultList <- list("annotation" = annotation)
  groupNames <- rownames(groups$means)
  p <- PlotStars(fsom,
                   nodeSizes = groups$means_norm[[groupNames[1]]],
                   title = groupNames[1],
                   ...)
  resultList[[groupNames[1]]] <- p
  backgroundColors <- grDevices::colorRampPalette(
    c("#FFFFFF22","#00FFFF55","#FF000055"), alpha=TRUE)
  for (group in groupNames[-1]){
    #nodeSizes <-  groups$means_norm[[group]]
    p <- PlotStars(fsom,
                     backgroundValues = annotation[[group]],
                     title = group,
                     backgroundColors = backgroundColors,
                   nodeSizes = groups$means_norm[[group]],
                     ...)
    resultList[[group]] <- p
  }
  return(resultList)
}

#' Calculate differences in cell counts between groups
#'
#' @param  fsom     FlowSOM object as generated by BuildSOM
#' @param  groups   List containing an array with file names for each group
#' @param  plot     Logical. If TRUE, make a starplot of each individual file
#' @param  silent   Logical. If TRUE, print progress messages
#'
#' @return Distance matrix
#' 
#' @seealso GroupStats
#'
#' @examples
#' set.seed(1)
#' fileName <-  system.file("extdata", "68983.fcs", package="FlowSOM")
#' flowSOM.res <- FlowSOM(fileName, compensate = TRUE, transform = TRUE,
#'                       scale = TRUE, colsToUse = c(9,12,14:18), nClus = 10)
#' 
#' ff <- flowCore::read.FCS(fileName)
#' # Make an additional file without cluster 7 and double amount of cluster 5
#' selection <- c(which(GetClusters(flowSOM.res) %in% 
#'                                  which(flowSOM.res$metaclustering != 7)),
#'                  which(GetClusters(flowSOM.res) %in% 
#'                                  which(flowSOM.res$metaclustering == 5)))
#' ff_tmp <- ff[selection,]
#' flowCore::write.FCS(ff_tmp, file="ff_tmp.fcs")
#' 
#' # Compare only the file with the double amount of cluster 10
#' features <- GetFeatures(flowSOM.res, 
#'                         c(fileName, "ff_tmp.fcs"),
#'                         level = "clusters",
#'                         type = "percentages")
#' stats <- GroupStats(features$cluster_percentages,                     
#'                     groups = list("AllCells" = c(fileName),
#'                                   "Without_ydTcells" = c("ff_tmp.fcs")))
#'
#' @export 
CountGroups <- function (fsom, groups, plot = TRUE, silent = FALSE) 
{
  .Deprecated("GetFeatures and Groupstats")
  if (is(groups[[1]], "character")) {
    files <- unlist(groups)
    counts <- matrix(0, nrow = length(files), ncol = fsom$map$nNodes, 
                     dimnames = list(files, as.character(1:fsom$map$nNodes)))
    for (file in files) {
      if (!silent) {
        print(file)
      }
      ff <- flowCore::read.FCS(file)
      fsom_f <- NewData(fsom, ff)
      if (plot) {
        PlotStars(fsom_f, title = file)
      }
      tmp <- table(fsom_f$map$mapping[, 1])
      counts[file, names(tmp)] <- tmp
    }
    nGroups <- lapply(groups, 
                      length)
  }
  else {
    counts <- do.call(rbind, groups)
    nGroups <- lapply(groups, 
                      nrow)
  }
  pctgs <- t(sapply(seq_len(nrow(counts)), function(i) {
    counts[i, ]/rowSums(counts)[i]
  }))
  means <- apply(pctgs, 2, function(x) {
    tapply(x, INDEX = factor(rep(names(groups), nGroups), 
                             levels = names(groups)), mean)
  })
  means <- means + 0.00000000000000000001
  medians <- apply(pctgs, 2, function(x) {
    tapply(x, INDEX = factor(rep(names(groups), nGroups), 
                             levels = names(groups)), stats::median)
  })
  medians <- medians + 0.00000000000000000001
  means_norm <- list()
  for (group in names(groups)) {
    means_norm[[group]] <- (means[group, ] - min(means))/(max(means) - 
                                                            min(means))
  }
  list(groups = rep(names(groups), unlist(nGroups)), 
       counts = counts, pctgs = pctgs, means = means, medians = medians, 
       means_norm = means_norm)
}

#' query_multiple
#'
#' Function which takes a named list of multiple cell types, where every item is
#' a named vector with values "high"/"low" and the names correspond to the
#' markers or channels (e.g. as generated by parse_markertable).
#'
#' @param fsom       FlowSOM object
#' @param cell_types Description of the cell types. Named list, with one named
#'                   vector per cell type containing "high"/"low" values
#' @param pdf_name   Path to a pdf file to save figures
#' @param ...        Additional arguments to pass to \code{\link{QueryStarPlot}}
#'
#' @return A label for every FlowSOM cluster (Unknown or one of the celltype
#'         names of the list, if selected by QueryStarPlot)
#'         
#' @seealso \code{\link{QueryStarPlot}}
#' 
#' @examples
#'    file <- system.file("extdata", "68983.fcs", package="FlowSOM")
#'    ff <- flowCore::read.FCS(file)
#'    # Use the wrapper function to build a flowSOM object (saved in flowSOM.res)
#'    # and a metaclustering (saved in flowSOM.res[["metaclustering"]])
#'    flowSOM.res <- FlowSOM(ff,compensate = TRUE, transform = TRUE,scale = TRUE,
#'                   colsToUse = c(9,12,14:18), nClus = 10, silent = FALSE,
#'                   xdim=7, ydim=7)
#'    cell_types <- list("CD8 T cells" = c("PE-Cy7-A" = "high",
#'                                         "APC-Cy7-A" = "high",
#'                                         "Pacific Blue-A" = "high"),
#'                        "B cells" = c("PE-Cy5-A" = "high"),
#'                        "NK cells" = c("PE-A" = "high",
#'                                       "PE-Cy7-A" = "low",
#'                                       "APC-Cy7-A" = "low"))
#'    query_res <- QueryMultiple(flowSOM.res, cell_types, "query_multiple.pdf")
#'    
#' @export
query_multiple <- function(fsom,
                           cell_types,
                           pdf_name = "query_multiple.pdf",
                           ...){
  .Deprecated("QueryMultiple")
  labels <- QueryMultiple(fsom, cell_types, pdf_name)
  return(labels)
}

#' PlotNode
#' Plot star chart
#' 
#' Plot a star chart indicating median marker values of a single node
#' 
#' @param fsom     FlowSOM object, as generated by \code{\link{BuildMST}} or
#'                 the first element of the list returned by 
#'                 \code{\link{FlowSOM}}
#' @param id       Id of the node to plot (check PlotNumbers to get the ids)
#' @param markers  Array of markers to use. Default: the markers used to build 
#'                 the tree
#' @param colorPalette      Color palette to be used for the markers
#' @param main     Title of the plot
#' 
#' @return Nothing is returned. A plot is drawn in which the node is 
#' represented by a star chart indicating the median fluorescence intensities.
#' 
#' @seealso \code{\link{PlotStars}},\code{\link{PlotNumbers}},
#'  \code{\link{FlowSOM}}
#' 
#' @examples
#'    # Read from file, build self-organizing map and minimal spanning tree
#'    fileName <- system.file("extdata", "68983.fcs", package="FlowSOM")
#'    flowSOM.res <- FlowSOM(fileName, compensate=TRUE,transform=TRUE,
#'                             scale=TRUE,colsToUse=c(9,12,14:18),nClus=10)
#'    
#'    # Deprecated, it is currently not possible anymore to plot an individual
#'    # node alone. If necessary, zooming in on a node can be approximated by
#'    # exagerating the size of the node.
#'    PlotStars(flowSOM.res, nodeSizes = c(100, rep(0,99)), maxNodeSize = 10)
#'
#' @export
PlotNode <- function(fsom, id, 
                     markers=fsom$map$colsUsed, 
                     colorPalette=grDevices::colorRampPalette(
                       c("#00007F", "blue", "#007FFF", "cyan", "#7FFF7F", 
                         "yellow", "#FF7F00", "red", "#7F0000")),
                     main=paste0("Cluster ",id)){
  .Deprecated("geom_arc_bar from ggforce")
  graphics::plot(1, type="n", xlab="", ylab="", 
                 xlim=c(-10, 10), ylim=c(-3, 3),asp=1,
                 bty="n",xaxt="n",yaxt="n",main=main)
  
  labels <- fsom$prettyColnames[markers]
  n <- length(markers)
  
  if(is.function(colorPalette)){colorPalette <- colorPalette(n)}
  data <- rbind(apply(fsom$map$medianValues[, markers,drop=FALSE],2,min, 
                      na.rm = TRUE),
                fsom$map$medianValues[id, markers,drop=FALSE],
                apply(fsom$map$medianValues[, markers,drop=FALSE],2,max, 
                      na.rm = TRUE))
  coords <- matrix(c(100,0,100,100,0,100),nrow=3)
  
  print(data)
  graphics::stars(data,col.segments=colorPalette,
                  locations=coords,
                  draw.segments = TRUE,add=TRUE,
                  inches=FALSE)
  
  graphics::symbols(coords[, 1], coords[, 2], circles = c(1,1,1), 
                    inches = FALSE, bg = "transparent", bty='n', add=TRUE) 
  
  angle <- 2*pi / n
  angles <- seq(angle/2,2*pi,by=angle)
  
  left <- (angles > (pi/2) & angles < (3*pi/2))
  x <- c(2,-2)[left+1]
  y_tmp <- c(seq(-2,2,by= 4/(sum(!left)+1))[-c(1,sum(!left)+2)],
             seq(2,-2,by=-4/(sum(left)+1))[-c(1,sum(left)+2)])
  shiftFunction <- function(x,n){
    c(x[(n+1):length(x)],x[1:n])
  }
  y <- shiftFunction(y_tmp,max((cummax(y_tmp)<0)*seq_along(y_tmp)))
  
  for(i in seq_along(labels)){
    graphics::text(x= x[i], 
                   y= y[i],
                   labels=labels[i],
                   adj = c(as.numeric(left)[i],0.5),
                   cex = 0.5)
    
    graphics::lines(x=c(x[i]+c(-0.2,0.2)[left[i]+1],
                        c(1.5,-1.5)[left[i]+1],
                        cos(angles[i])),
                    y=c(y[i],
                        y[i],
                        sin(angles[i])),
                    col=colorPalette[i],
                    lwd=2)    
  }
}


#' PlotCenters
#'
#' Plot cluster centers on a 2D plot
#' 
#' Plot FlowSOM nodes on a 2D scatter plot of the data
#' 
#' @param fsom    FlowSOM object, as generated by \code{\link{BuildMST}}
#' @param marker1 Marker to show on the x-axis
#' @param marker2 Marker to show on the y-axis
#' @param MST     Type of visualization, if 1 plot tree, else plot grid
#' @return Nothing is returned. A 2D scatter plot is drawn on which the nodes 
#'         of the grid are indicated
#'         
#' @seealso \code{\link{PlotStars}},\code{\link{PlotPies}},
#'          \code{\link{PlotMarker}},\code{\link{BuildMST}}
#'          
#' @examples
#'    # Read from file, build self-organizing map and minimal spanning tree
#'    fileName <- system.file("extdata", "68983.fcs", package="FlowSOM")
#'    flowSOM.res <- ReadInput(fileName, compensate=TRUE,transform=TRUE,
#'                             scale=TRUE)
#'    flowSOM.res <- BuildSOM(flowSOM.res,colsToUse=c(9,12,14:18))
#'    flowSOM.res <- BuildMST(flowSOM.res)
#'    
#'    # Plot centers
#'    plot <- Plot2DScatters(flowSOM.res,
#'                   channelpairs = list(c("FSC-A","SSC-A")),
#'                   clusters = list(seq_len(NClusters(flowSOM.res))),
#'                   maxPoints = 0,
#'                   plotFile = NULL)
#'                   
#' @importFrom igraph get.edges E
#' @importFrom stats dist
#' @importFrom graphics lines
#'
#' @export
PlotCenters <- function(fsom, marker1, marker2, MST=TRUE){
  .Deprecated("Plot2DScatters")
  graphics::plot(fsom$data[, c(marker1, marker2)], pch=".", col="#000000AA")
  d <- fsom$map$medianValues[, c(marker1, marker2)]
  graphics::points(d,col="red")
  
  if(MST==1){
    g <- fsom$MST$graph
    e <- igraph::get.edges(g, E(g))
  } else {
    e <- which(as.matrix(
      stats::dist(fsom$map$grid,method = "manhattan"))==1,
      arr.ind=TRUE)
  }
  
  for(i in seq_len(nrow(e))){
    graphics::lines(d[c(e[i, 1], e[i, 2]), 1], 
                    d[c(e[i, 1], e[i, 2]), 2], 
                    col="red")
  }
}