#!/usr/bin/env Rscript-3.4.4

# Replace low count data with NULL
hide.low.point<-function(data,thre=50){
    data[(data$TP+data$FN)<thre,]$Sensitivity <- "NULL"
    data[(data$TN+data$FP)<thre,]$Specificity <- "NULL"
    data
}

get.rank.data<-function(data){
    sp.levels = levels(as.factor(data$species))
    db.levels = levels(as.factor(data$database))
    outdata = data.frame()
    for (mysp in sp.levels){
        for (mydb in db.levels){
            sp.db.data = subset(data,database == mydb & species == mysp)
            sp.db.data$Sen.rank = rank(sp.db.data$Sensitivity)
            sp.db.data$Spe.rank = rank(sp.db.data$Specificity)
            outdata = rbind(outdata,sp.db.data)
        }
    }
    outdata
}

get.rank <- function(data,which,fake){
    if (which == "both"){
        if (length(data[,1]) == 0){
            fake
        } else{
            data[,c("species","methods","Sen.rank","Spe.rank")]
        }
    } else if (which == "Sen"){
        if (length(data[,1]) == 0){
            fake[,c("species","methods","Sen.rank")]
        } else{
            data[,c("species","methods","Sen.rank")]
        }
    } else if (which == "Spe"){
        if (length(data[,1]) == 0){
            fake[,c("species","methods","Spe.rank")]
        } else{
            data[,c("species","methods","Spe.rank")]
        }
    } else {
        print("which must be one of both, Sen or Spe.")
    }
}
# input rank data from get.rank.data
# output data:
# header: species, methods, Sen_0, Sen_1, Sen_2, Spe_2
get.pure.rank.data<-function(data){
    sp.levels = levels(as.factor(data$species))
    #outdata = data.frame(species=c(),methods=c(),Sen_0=c(),Sen_1=c(),Sen_2=c(),Spe_2=c())
    outdata = data.frame()
    for (mysp in sp.levels){
        sp.data = subset(data, species == mysp)
        # make fake data
        fake.rank = 0.5+length(levels(data$methods))/2
        fake.data = data.frame(species=mysp,methods=levels(data$methods),Sen.rank=fake.rank,Spe.rank=fake.rank)

        db_0 <- get.rank(subset(sp.data, database == "0"), which = "Sen",fake=fake.data)
        db_1 <- get.rank(subset(sp.data, database == "1"), which = "Sen",fake=fake.data)
        db_2 <- get.rank(subset(sp.data, database == "2"), which = "both",fake=fake.data)
        #print(head(db_0))
        #print(head(db_1))
        #print(head(db_2))
        m01 = merge(db_0,db_1,by=c("species","methods"))
        m012 = merge(m01,db_2,by=c("species","methods"))
        colnames(m012)<-c("species","methods","Sen.0","Sen.1","Sen.2","Spe.2")
        outdata = rbind(outdata,m012)
    }
    outdata
}
#merge.rank <- function(data,sp.levels,db.levels){
#}


# Merge ranks of each spe, db on Sen
# input data:
# header: species, methods, Sen_0, Sen_1, Sen_2, Spe_2
merge.rank.sen <- function(data){
    # init merge.sen
    data$Merge.Sen = 1
    sp.levels = unique(data$species)
    for (mysp in sp.levels){
        spdata = data[data$species == mysp,]
        data[data$species == mysp,]$Merge.Sen = rank(spdata$Sen.0+spdata$Sen.1+spdata$Sen.2)
    }
    data
}

merge.rank.all <- function(data){
    data$Merge.All = 1
    sp.levels = unique(data$species)
    for (mysp in sp.levels){
        spdata = data[data$species == mysp,]
        data[data$species == mysp,]$Merge.All = rank(spdata$Merge.Sen+spdata$Spe.2)
    }
    data
}

# input SpeDB.astat file
# output 
#                 species        methods Sen.0 Sen.1 Sen.2 Spe.2 Merge.Sen Merge.All
#1 Ailuropoda melanoleuca        CNCI_pl  11.0  18.5  18.5  17.5      11.0  11.0
#2 Ailuropoda melanoleuca        CNCI_ve  18.0  18.5  18.5  15.0      18.0  16.0
#3 Ailuropoda melanoleuca       cpat_fly  22.0  18.5  18.5  17.5      22.0  21.0
#4 Ailuropoda melanoleuca     cpat_human  30.5  18.5  18.5  25.0      30.5  34.0
#5 Ailuropoda melanoleuca     cpat_mouse  30.5  18.5  18.5  16.0      30.5  26.5
#6 Ailuropoda melanoleuca cpat_zebrafish  18.0  18.5  18.5  28.5      18.0  26.5
# ... ... 
get.merged.rank.data <- function(infile,mythre){
    data <- read.table(infile,header=T,sep="\t")
    data <- hide.low.point(data,mythre)
    rank.data <- get.rank.data(data)
    pure.rank.data <- get.pure.rank.data(rank.data)
    msen.pure.rank.data <- merge.rank.sen(pure.rank.data)
    merge.rank.all(msen.pure.rank.data)
}

# merge_spe: new species name of merged rank.
merge_spes <- function(data,merge_spe){
    outdata = data.frame(species=character(),methods=character(),Sen.0=double(),Sen.1=double(),Sen.2=double(),Spe.2=double(),Merge.Sen=double(),Merge.All=double(),stringsAsFactors=F)
    for (mymthd in unique(data$methods)){
        method.data <- subset(data,methods == mymthd)
        outdata=rbind(outdata,c(merge_spe,mymthd,apply(method.data[,c(3,4,5,6,7,8)],2,sum)),stringsAsFactors=F)
    }
    colnames(outdata)<-c("species","methods","Sen.0","Sen.1","Sen.2","Spe.2","Merge.Sen","Merge.All")
    outdata$Sen.0 <-  rank(as.numeric(outdata$Sen.0))
    outdata$Sen.1 <-  rank(as.numeric(outdata$Sen.1))
    outdata$Sen.2 <-  rank(as.numeric(outdata$Sen.2))
    outdata$Spe.2 <-  rank(as.numeric(outdata$Spe.2))
    outdata$Merge.Sen <-  rank(as.numeric(outdata$Merge.Sen))
    outdata$Merge.All <-  rank(as.numeric(outdata$Merge.All))
    outdata
}

merge.spe <- function(data,spe_list,spe_name){
    mydata <- subset(data,species %in% spe_list)
    merge_spes(mydata,spe_name)
}
merge.mammalian<-function(data){
    mammalian<-c("Ornithorhynchus anatinus","Callithrix jacchus","Macaca fascicularis","Macaca mulatta","Macaca nemestrina","Papio anubis","Gorilla gorilla","Pan troglodytes","Pongo abelii","Homo sapiens","Ailuropoda melanoleuca","Felis catus","Equus caballus","Sus scrofa","Bos taurus","Capra hircus","Ovis aries","Oryctolagus cuniculus","Mesocricetus auratus","Mus musculus","Rattus norvegicus","Cavia porcellus","Monodelphis domestica")
    mydata <- subset(data,species %in% mammalian)
    merge_spes(mydata,"mammalian")
}

merge.plant<-function(data){
    plant<-c("Arabidopsis thaliana", "Brassica napus", "Solanum tuberosum", "Zea mays")
    merge.spe(data,plant,"plant")
}

merge.fish<-function(data){
    fish<-c("Danio rerio", "Oreochromis niloticus")
    merge.spe(data,fish,"fish")
}

infile = "smallRNE_core_all_SpeDB.astat"
outfile = "smallRNE_core_all_SpeDB.rank.astat"
mythre = 50
rank.data <- get.merged.rank.data(infile,mythre)
# get merged all rank data
all.rank <- merge_spes(rank.data,"all")
rank.data <- rbind(rank.data,all.rank)
# get merged mammalian rank data
mamma.rank <- merge.mammalian(rank.data)
fish.rank <- merge.fish(rank.data)
plant.rank <- merge.plant(rank.data)
rank.data <- rbind(rank.data, mamma.rank, fish.rank, plant.rank)

####rank.data <- rbind(rank.data,mamma.rank)
# get merged plant rank data
write.table(rank.data,outfile,sep="\t",quote=F,row.names=F)
