#' Normalize CRISPR counts in a SummarizedExperiment
#'
#' Compute (log-)normalized expression values after performing scaling normalization of an CRISPR count matrix.
#' This calls \code{\link{normalizeCounts}} on an assay of a \link[SummarizedExperiment]{SummarizedExperiment},
#' after centering the size factors with \code{\link{centerSizeFactors}}.
#'
#' @param x A \link[SummarizedExperiment]{SummarizedExperiment} object or one of its subclasses.
#' Rows correspond to CRISPR guides and columns correspond to cells.
#' @param size.factors Numeric vector of length equal to the number of columns of \code{x},
#' containing the size factor for each cell in \code{x}.
#' If \code{NULL}, this defaults to the column sums of the count matrix in \code{x}.
#' @param center Logical scalar indicating whether to center the \code{size.factors},
#' see \code{?\link{centerSizeFactors}} for more details.
#' @param block Block assignments for each cell, passed to \code{\link{centerSizeFactors}}.
#' @param mode How to center size factors in different blocks, see \code{?\link{centerSizeFactors}} for more details.
#' @param log Whether to log-transform the normalized expression values, see \code{?\link{normalizeCounts}} for more details.
#' @param pseudo.count The pseudo-count for log-transformation, see \code{?\link{normalizeCounts}} for more details.
#' @param more.norm.args Named list of additional arguments to pass to \code{\link{normalizeCounts}}.
#' @param assay.type Integer or string specifying the assay of \code{x} with the count matrix.
#' @param output.name String containing the name of the assay to store the normalized matrix.
#' @param factor.name String containing the name of the \code{\link[SummarizedExperiment]{colData}} column in which to store the size factors in the output object.
#' If \code{NULL}, the size factors are not stored. 
#' @param num.threads Integer specifying the number of threads for computing column sums.
#' Only used if \code{size.factors=NULL}.
#'
#' @return \code{x} is returned with a new assay containing the (log-)normalized matrix.
#' Size factors are also stored in the \code{\link[SummarizedExperiment]{colData}}.
#'
#' @author Aaron Lun
#'
#' @examples
#' library(SingleCellExperiment)
#' sce <- altExp(getTestCrisprData.se("qc"), "CRISPR Guide Capture")
#' sce <- normalizeCrisprCounts.se(sce, size.factors=sce$sum)
#' assayNames(sce)
#' summary(sizeFactors(sce))
#'
#' @export
#' @importFrom beachmat initializeCpp tatami.column.sums
normalizeCrisprCounts.se <- function(
    x,
    size.factors = NULL,
    center = TRUE,
    block = NULL,
    mode = "lowest",
    log = TRUE,
    pseudo.count = 1,
    more.norm.args = list(),
    assay.type = "counts",
    output.name = "logcounts",
    factor.name = "sizeFactor",
    num.threads = 1
) {
    y <- SummarizedExperiment::assay(x, assay.type)

    if (is.null(size.factors)) {
        size.factors <- tatami.column.sums(initializeCpp(y), num.threads=num.threads)
    }
    if (center) {
        size.factors <- centerSizeFactors(size.factors, block=block, mode=mode)
    }

    SummarizedExperiment::assay(x, output.name) <- .call(
        normalizeCounts,
        list(y, size.factors=size.factors),
        list(log=log, pseudo.count=pseudo.count),
        more.norm.args
    )

    if (!is.null(factor.name)) {
        SummarizedExperiment::colData(x)[[factor.name]] <- size.factors
    }

    x
}
