### =========================================================================
### "coverage" methods
### -------------------------------------------------------------------------


setMethod("coverage", "GAlignments",
    function(x, shift=0L, width=NULL, weight=1L,
                method=c("auto", "sort", "hash", "naive"), drop.D.ranges=FALSE)
    {
        x <- grglist(x, drop.D.ranges=drop.D.ranges)
        coverage(x, shift=shift, width=width, weight=weight, method=method)
    }
)

setMethod("coverage", "GAlignmentPairs",
    function(x, shift=0L, width=NULL, weight=1L,
                method=c("auto", "sort", "hash", "naive"), drop.D.ranges=FALSE)
    {
        x <- grglist(x, drop.D.ranges=drop.D.ranges)
        ## Should we do this instead?
        ## See https://support.bioconductor.org/p/123463/#123552
        #x <- reduce(grglist(x, drop.D.ranges=drop.D.ranges))
        coverage(x, shift=shift, width=width, weight=weight, method=method)
    }
)

setMethod("coverage", "GAlignmentsList",
    function(x, shift=0L, width=NULL, weight=1L, ...)
    {
        x <- unlist(x, use.names=FALSE)
        callGeneric()
    }
)

setMethod("coverage", "BamFile",
    function(x, shift=0L, width=NULL, weight=1L, ..., param=ScanBamParam())
{
    if (!isOpen(x)) {
        open(x)
        on.exit(close(x))
    }

    cvg <- NULL
    repeat {
        aln <- readGAlignments(x, param=param)
        if (length(aln) == 0L) {
            if (is.null(cvg))
                cvg <- coverage(aln, shift=shift, width=width, 
                                weight=weight, ...)
            break
        }
        cvg0 <- coverage(aln, shift=shift, width=width, weight=weight, ...)
        if (is.null(cvg))
            cvg <- cvg0
        else
            cvg <- cvg + cvg0
    }
    cvg
})

setMethod("coverage", "character",
    function(x, shift=0L, width=NULL, weight=1L, ..., yieldSize=2500000L)
{
    if (!isSingleString(x))
        stop("'x' must be a single string for coverage,character-method")
    bf <- BamFile(x, yieldSize=yieldSize)
    coverage(bf, shift=shift, width=width, weight=weight, ...)
})

