gageAnalysis <- function(
        ptn,
        category,
        genesSlopeFiltOut = NULL,
        maxSize = 500,
        minSize = 10
) {
    check_ptn(ptn)
    species <- ptn_species(ptn)
    
    if (!species %in% c("human", "mouse")) {
        stop(
            "GAGE analysis functionality is currently only available ",
            "for human and mouse."
        )
    }
    
    if (!check_number(maxSize) || !check_number(minSize)) {
        stop("The inputs for 'maxSize' and 'minSize' must be integers.")
    }
    
    if (minSize <= 0 || maxSize <= 0) {
        stop("The inputs for 'maxSize' and 'minSize' must be positive.")
    }
    
    if (maxSize <= minSize) {
        stop("'maxSize' must be greater than 'minSize'.")
    }
    
    effTmp <- ptn_effect(ptn)
    
    if (!is.null(genesSlopeFiltOut)) {
        effIn <- effTmp[!names(effTmp) %in% genesSlopeFiltOut]
    } else {
        effIn <- effTmp
    }
    
    convTab <- convertSymbolToEntrezID(names(effIn), species = species)
    names(convTab) <- convertEntrezIDToSymbol(convTab, species = species)
    
    names(effIn) <- as.character(convTab)[match(names(effIn), names(convTab))]
    effIn <- effIn[!is.na(names(effIn))]
    rankIn <- effIn[order(effIn, decreasing = TRUE)]
    
    GAGEout <- new(
        "postNetGAGE",
        BP = NULL,
        CC = NULL,
        MF = NULL,
        KEGG = NULL
    )
    
    pathwayGO <- NULL
    
    for (sel in category) {
        if (sel == "KEGG") {
            pathwayKegg <- gage::kegg.gsets(
                species = species,
                id.type = "entrez"
            )
            
            pathwaysIn <- pathwayKegg$kg.sets
        } else {
            if (is.null(pathwayGO)) {
                pathwayGO <- gage::go.gsets(species = species, id.type = "EG")
            }
            
            if (sel == "BP") {
                pathwaysIn <- pathwayGO$go.sets[pathwayGO$go.subs$BP]
            } else if (sel == "MF") {
                pathwaysIn <- pathwayGO$go.sets[pathwayGO$go.subs$MF]
            } else if (sel == "CC") {
                pathwaysIn <- pathwayGO$go.sets[pathwayGO$go.subs$CC]
            }
        }
        
        resOut <- gage::gage(
            exprs = rankIn,
            gsets = pathwaysIn,
            set.size = c(minSize, maxSize),
            rank.test = TRUE,
            use.fold = FALSE
        )
        
        pathwaysGenes <- list()
        
        for (pw in seq_along(pathwaysIn)) {
            glist <- unlist(pathwaysIn[pw])
            tmpGenes <- glist[glist %in% names(rankIn)]
            
            if (length(tmpGenes) > 0) {
                tmpGenes_conv <- names(convTab)[
                    match(as.character(tmpGenes), convTab)
                ]
            } else {
                tmpGenes_conv <- NA
            }
            
            pathwaysGenes[[pw]] <- paste(tmpGenes_conv, collapse = ":")
        }
        
        names(pathwaysGenes) <- names(pathwaysIn)
        
        pathwaysGenes <- pathwaysGenes[as.numeric(which(unlist(lapply(
            pathwaysGenes,
            function(x) {
                x != "NA"
            }
        ))))]
        
        if (nrow(resOut$greater) > 0) {
            grTmpG <- resOut$greater
            grTmpG <- grTmpG[, c(1, 2, 5, 3, 4)]
            grTmpG <- data.frame(id = row.names(grTmpG), grTmpG, row.names = NULL)
            
            grTmpG$Genes <- as.character(pathwaysGenes)[
                match(grTmpG$id, names(pathwaysGenes))
            ]
            
            resOut$greater <- grTmpG
        }
        
        if (nrow(resOut$less) > 0) {
            grTmpL <- resOut$less
            grTmpL <- grTmpL[, c(1, 2, 5, 3, 4)]
            grTmpL <- data.frame(id = row.names(grTmpL), grTmpL, row.names = NULL)
            
            grTmpL$Genes <- as.character(pathwaysGenes)[
                match(grTmpL$id, names(pathwaysGenes))
            ]
            
            resOut$less <- grTmpL
        }
        
        slot(GAGEout, sel) <- resOut
    }
    
    ptn@analysis@GAGE <- GAGEout
    
    return(ptn)
}
