############################################################
## Here we're checking the returnFilterColumns setting, i.e.
## whether also filter columns should be returned or not.
library(EnsDb.Hsapiens.v75)
edb <- EnsDb.Hsapiens.v75

## Testing the internal function.
test_set_returnFilterColumns <- function(x) {
    orig <- returnFilterColumns(edb)
    returnFilterColumns(edb) <- TRUE
    checkEquals(TRUE, returnFilterColumns(edb))
    returnFilterColumns(edb) <- FALSE
    checkEquals(FALSE, returnFilterColumns(edb))
    checkException(returnFilterColumns(edb) <- "d")
    checkException(returnFilterColumns(edb) <- c(TRUE, FALSE))
    ## Restore the "original" setting
    returnFilterColumns(edb) <- orig
}

test_with_genes <- function(x) {
    orig <- returnFilterColumns(edb)

    returnFilterColumns(edb) <- FALSE
    ## What happens if we use a GRangesFilter with return filter cols FALSE?
    grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)))
    res <- genes(edb, filter = grf)
    checkEquals(res$gene_id, c("ENSG00000224738", "ENSG00000182628", "ENSG00000252212",
                               "ENSG00000211514", "ENSG00000207996"))
    cols <- c("gene_id", "gene_name")
    res <- genes(edb, filter = grf, return.type = "data.frame",
                 columns = cols)
    ## Expect only the columns
    checkEquals(colnames(res), cols)
    returnFilterColumns(edb) <- TRUE
    res <- genes(edb, filter = grf, return.type = "data.frame",
                 columns = cols)
    ## Now I expect also the gene coords.
    checkEquals(colnames(res), c(cols, "gene_seq_start", "gene_seq_end", "seq_name",
                                 "seq_strand"))

    ## Use a gene biotype filter
    gbt <- GenebiotypeFilter("protein_coding")

    returnFilterColumns(edb) <- TRUE
    res <- genes(edb, filter = list(gbt, grf), return.type = "data.frame",
                 columns = cols)
    checkEquals(res$gene_name, "SKA2")
    checkEquals(colnames(res), c(cols, "gene_biotype", "gene_seq_start", "gene_seq_end",
                                 "seq_name", "seq_strand"))
    returnFilterColumns(edb) <- FALSE
    res <- genes(edb, filter = list(gbt, grf), return.type = "data.frame",
                 columns = cols)
    checkEquals(colnames(res), cols)

    returnFilterColumns(edb) <- orig
}


test_with_tx <- function(x) {
    orig <- returnFilterColumns(edb)

    returnFilterColumns(edb) <- FALSE
    ## What happens if we use a GRangesFilter with return filter cols FALSE?
    grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)))
    res <- transcripts(edb, filter = grf)
    cols <- c("tx_id", "gene_name")
    res <- transcripts(edb, filter = grf, return.type = "data.frame",
                       columns = cols)
    ## Expect only the columns
    checkEquals(colnames(res), cols)
    returnFilterColumns(edb) <- TRUE
    res <- transcripts(edb, filter = grf, return.type = "data.frame",
                       columns = cols)
    ## Now I expect also the gene coords.
    checkEquals(colnames(res), c(cols, "tx_seq_start", "tx_seq_end", "seq_name",
                                 "seq_strand"))

    ## Use a gene biotype filter
    gbt <- GenebiotypeFilter("protein_coding")

    returnFilterColumns(edb) <- TRUE
    res <- transcripts(edb, filter = list(gbt, grf), return.type = "data.frame",
                       columns = cols)
    checkEquals(unique(res$gene_name), "SKA2")
    checkEquals(colnames(res), c(cols, "gene_biotype", "tx_seq_start", "tx_seq_end",
                                 "seq_name", "seq_strand"))
    returnFilterColumns(edb) <- FALSE
    res <- transcripts(edb, filter = list(gbt, grf), return.type = "data.frame",
                       columns = cols)
    checkEquals(colnames(res), cols)

    returnFilterColumns(edb) <- orig
}


test_with_exons <- function(x) {
    orig <- returnFilterColumns(edb)

    returnFilterColumns(edb) <- FALSE
    ## What happens if we use a GRangesFilter with return filter cols FALSE?
    grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)))
    res <- exons(edb, filter = grf)
    cols <- c("exon_id", "gene_name")
    res <- exons(edb, filter = grf, return.type = "data.frame",
                 columns = cols)
    ## Expect only the columns
    checkEquals(colnames(res), cols)
    returnFilterColumns(edb) <- TRUE
    res <- exons(edb, filter = grf, return.type = "data.frame",
                 columns = cols)
    ## Now I expect also the gene coords.
    checkEquals(colnames(res), c(cols, "exon_seq_start", "exon_seq_end", "seq_name",
                                 "seq_strand"))

    ## Use a gene biotype filter
    gbt <- GenebiotypeFilter("protein_coding")

    returnFilterColumns(edb) <- TRUE
    res <- exons(edb, filter = list(gbt, grf), return.type = "data.frame",
                 columns = cols)
    checkEquals(unique(res$gene_name), c("TRIM37", "SKA2"))
    checkEquals(colnames(res), c(cols, "gene_biotype", "exon_seq_start", "exon_seq_end",
                                 "seq_name", "seq_strand"))
    returnFilterColumns(edb) <- FALSE
    res <- exons(edb, filter = list(gbt, grf), return.type = "data.frame",
                 columns = cols)
    checkEquals(colnames(res), cols)

    returnFilterColumns(edb) <- orig
}

test_with_exonsBy <- function(x) {
    orig <- returnFilterColumns(edb)

    returnFilterColumns(edb) <- FALSE
    ## What happens if we use a GRangesFilter with return filter cols FALSE?
    grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)))
    ## By genes
    cols <- c("exon_id", "gene_name")
    res <- exonsBy(edb, by = "gene", filter = grf, columns = cols)
    res <- unlist(res)
    ## Expect only the columns
    checkEquals(colnames(mcols(res)), cols)

    returnFilterColumns(edb) <- TRUE
    res <- exonsBy(edb, by = "gene", filter = grf, columns = cols)
    res <- unlist(res)
    ## Now I expect also the gene coords, but not the seq_name and seq_strand, as these
    ## are redundant with data which is in the GRanges!
    checkEquals(colnames(mcols(res)), c(cols, "gene_seq_start", "gene_seq_end"))

    ## Use a gene biotype filter
    gbt <- GenebiotypeFilter("protein_coding")

    returnFilterColumns(edb) <- TRUE
    res <- unlist(exonsBy(edb, by = "gene", filter = list(gbt, grf), columns = cols))
    checkEquals(unique(res$gene_name), c("SKA2"))
    checkEquals(colnames(mcols(res)), c(cols, "gene_biotype", "gene_seq_start", "gene_seq_end"))
    returnFilterColumns(edb) <- FALSE
    res <- unlist(exonsBy(edb, by = "gene", filter = list(gbt, grf), columns = cols))
    checkEquals(colnames(mcols(res)), cols)

    ## By tx
    returnFilterColumns(edb) <- FALSE
    cols <- c("exon_id", "gene_name")
    res <- exonsBy(edb, by = "tx", filter = grf, columns = cols)
    res <- unlist(res)
    ## Expect only the columns
    checkEquals(colnames(mcols(res)), c(cols, "exon_rank"))

    returnFilterColumns(edb) <- TRUE
    res <- exonsBy(edb, by = "tx", filter = grf, columns = cols)
    res <- unlist(res)
    ## Now I expect also the gene coords.
    checkEquals(colnames(mcols(res)), c(cols, "tx_seq_start", "tx_seq_end",
                                        "exon_rank"))

    ## Use a gene biotype filter
    gbt <- GenebiotypeFilter("protein_coding")

    returnFilterColumns(edb) <- TRUE
    res <- unlist(exonsBy(edb, by = "tx", filter = list(gbt, grf), columns = cols))
    checkEquals(unique(res$gene_name), c("SKA2"))
    checkEquals(colnames(mcols(res)), c(cols, "gene_biotype", "tx_seq_start", "tx_seq_end",
                                        "exon_rank"))
    returnFilterColumns(edb) <- FALSE
    res <- unlist(exonsBy(edb, by = "tx", filter = list(gbt, grf), columns = cols))
    checkEquals(colnames(mcols(res)), c(cols, "exon_rank"))

    returnFilterColumns(edb) <- orig
}


test_with_transcriptsBy <- function(x) {
    orig <- returnFilterColumns(edb)

    returnFilterColumns(edb) <- FALSE
    ## What happens if we use a GRangesFilter with return filter cols FALSE?
    grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)))
    ## By genes
    cols <- c("tx_id", "gene_name")
    res <- transcriptsBy(edb, by = "gene", filter = grf, columns = cols)
    res <- unlist(res)
    ## Expect only the columns
    checkEquals(colnames(mcols(res)), cols)

    returnFilterColumns(edb) <- TRUE
    res <- transcriptsBy(edb, by = "gene", filter = grf, columns = cols)
    res <- unlist(res)
    ## Now I expect also the gene coords.
    checkEquals(colnames(mcols(res)), c(cols, "gene_seq_start", "gene_seq_end"))

    ## Use a gene biotype filter
    gbt <- GenebiotypeFilter("protein_coding")

    returnFilterColumns(edb) <- TRUE
    res <- unlist(transcriptsBy(edb, by = "gene", filter = list(gbt, grf), columns = cols))
    checkEquals(unique(res$gene_name), c("SKA2"))
    checkEquals(colnames(mcols(res)), c(cols, "gene_biotype", "gene_seq_start", "gene_seq_end"))
    returnFilterColumns(edb) <- FALSE
    res <- unlist(transcriptsBy(edb, by = "gene", filter = list(gbt, grf), columns = cols))
    checkEquals(colnames(mcols(res)), cols)

    ## ## By exon
    ## returnFilterColumns(edb) <- FALSE
    ## cols <- c("tx_id", "gene_name")
    ## res <- transcriptsBy(edb, by = "exon", filter = grf, columns = cols)
    ## res <- unlist(res)
    ## ## Expect only the columns
    ## checkEquals(colnames(mcols(res)), c(cols))

    ## returnFilterColumns(edb) <- TRUE
    ## res <- transcriptsBy(edb, by = "exon", filter = grf, columns = cols)
    ## res <- unlist(res)
    ## ## Now I expect also the gene coords.
    ## checkEquals(colnames(mcols(res)), c(cols, "exon_seq_start", "exon_seq_end"))

    ## ## Use a gene biotype filter
    ## gbt <- GenebiotypeFilter("protein_coding")

    ## returnFilterColumns(edb) <- TRUE
    ## res <- unlist(transcriptsBy(edb, by = "exon", filter = list(gbt, grf), columns = cols))
    ## checkEquals(unique(res$gene_name), c("SKA2", "TRIM37"))
    ## checkEquals(colnames(mcols(res)), c(cols, "gene_biotype", "exon_seq_start", "exon_seq_end"))
    ## returnFilterColumns(edb) <- FALSE
    ## res <- unlist(transcriptsBy(edb, by = "exon", filter = list(gbt, grf), columns = cols))
    ## checkEquals(colnames(mcols(res)), c(cols))

    returnFilterColumns(edb) <- orig
}

test_with_cdsBy <- function(x) {
    orig <- returnFilterColumns(edb)
    grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)))

    ## By tx
    returnFilterColumns(edb) <- FALSE
    cols <- c("gene_id", "gene_name")
    res <- cdsBy(edb, by = "tx", filter = grf, columns = cols)
    res <- unlist(res)
    ## Expect only the columns
    checkEquals(colnames(mcols(res)), c(cols, "exon_id", "exon_rank"))

    returnFilterColumns(edb) <- TRUE
    res <- cdsBy(edb, by = "tx", filter = grf, columns = cols)
    res <- unlist(res)
    ## Now I expect also the gene coords.
    checkEquals(colnames(mcols(res)), c(cols, "tx_seq_start", "tx_seq_end",
                                        "seq_name", "seq_strand", "exon_id", "exon_rank"))

    ## Use a gene biotype filter
    gbt <- GenebiotypeFilter("protein_coding")

    returnFilterColumns(edb) <- TRUE
    res <- unlist(cdsBy(edb, by = "tx", filter = list(gbt, grf), columns = cols))
    checkEquals(unique(res$gene_name), c("SKA2"))
    checkEquals(colnames(mcols(res)), c(cols, "gene_biotype", "tx_seq_start", "tx_seq_end",
                                        "seq_name", "seq_strand", "exon_id", "exon_rank"))
    returnFilterColumns(edb) <- FALSE
    res <- unlist(cdsBy(edb, by = "tx", filter = list(gbt, grf), columns = cols))
    checkEquals(colnames(mcols(res)), c(cols, "exon_id", "exon_rank"))

    returnFilterColumns(edb) <- orig
}

test_with_threeUTRsByTranscript <- function(x) {
    orig <- returnFilterColumns(edb)
    grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)))

    ## By tx
    returnFilterColumns(edb) <- FALSE
    cols <- c("gene_id", "gene_name")
    res <- threeUTRsByTranscript(edb, filter = grf, columns = cols)
    res <- unlist(res)
    ## Expect only the columns
    checkEquals(colnames(mcols(res)), c(cols, "exon_id", "exon_rank"))

    returnFilterColumns(edb) <- TRUE
    res <- threeUTRsByTranscript(edb, filter = grf, columns = cols)
    res <- unlist(res)
    ## Now I expect also the gene coords.
    checkEquals(colnames(mcols(res)), c(cols, "tx_seq_start", "tx_seq_end",
                                        "seq_name", "seq_strand", "exon_id", "exon_rank"))

    ## Use a gene biotype filter
    gbt <- GenebiotypeFilter("protein_coding")

    returnFilterColumns(edb) <- TRUE
    res <- unlist(threeUTRsByTranscript(edb, filter = list(gbt, grf), columns = cols))
    checkEquals(unique(res$gene_name), c("SKA2"))
    checkEquals(colnames(mcols(res)), c(cols, "gene_biotype", "tx_seq_start", "tx_seq_end",
                                        "seq_name", "seq_strand", "exon_id", "exon_rank"))
    returnFilterColumns(edb) <- FALSE
    res <- unlist(threeUTRsByTranscript(edb, filter = list(gbt, grf), columns = cols))
    checkEquals(colnames(mcols(res)), c(cols, "exon_id", "exon_rank"))

    returnFilterColumns(edb) <- orig
}

