.packageName <- "annotationTools"
compactList<-function(lst,l) {

	stopifnot(length(lst)==sum(l))
	clst<-vector('list',length(l))
	j<-1
	for (i in 1:length(l)) {
		clst[[i]]<-unlist(lst[j:(j+l[i]-1)])
		j<-j+l[i]
	}
	clst
}
getANNOTATION<-function(identifier,annot,diagnose=FALSE,identifierCol=1,annotationCol=15,noAnnotationSymbol=NA,noAnnotationProvidedSymbol='---',sep=' /// ')  {

	if (is.na(noAnnotationProvidedSymbol)) stop('Argument noAnnotationProvidedSymbol should be different from NA')
	if (!(is.na(noAnnotationSymbol))) {if (noAnnotationSymbol==noAnnotationProvidedSymbol) stop('Argument noAnnotationSymbol and noAnnotationProvidedSymbol should be different')}

	empty<-(is.na(identifier) | identifier=='')
	ind<-match(identifier,annot[,identifierCol])
	noentry<-(is.na(ind) & !empty)
	if (sum(empty)>0) {cat('Warning: one or more empty identifers in input\n')}
	if (sum(noentry)>0) {cat('Warning: one or more identifers not found in annotation\n')}
	
	annotation<-as.list(rep(noAnnotationSymbol,length(identifier)))
	annotation[complete.cases(ind)]<-annot[na.omit(ind),annotationCol]
	
	noannotation<-annotation==noAnnotationProvidedSymbol
	annotation[noannotation]<-noAnnotationSymbol 
	if (sum(noannotation)>0) warning('One or more identifers with no annotation provided')
	
	indMultAnnotation<-grep(sep,annotation)
	annotation[indMultAnnotation]<-lapply(annotation[indMultAnnotation],function(x) {strsplit(x,sep)[[1]]})

	if (diagnose) list(annotation,empty,noentry,noannotation)
	else annotation

}

getGENEID<-function(ps,annot,diagnose=FALSE,idCol=19,noIDsymbol=NA,noIDprovidedSymbol='---',sep=' /// ') {

	if (is.na(noIDprovidedSymbol)) stop('Argument noIDprovidedSymbol should be different from NA')
	if (!(is.na(noIDsymbol))) {if (noIDsymbol==noIDprovidedSymbol) stop('Argument noIDsymbol and noIDprovidedSymbol should be different')}
	
	empty<-(is.na(ps) | ps=='')
	ind<-match(ps,annot[,1])
	noentry<-(is.na(ind) & !empty)
	if (sum(empty)>0) warning('One or more empty probe sets in input')
	if (sum(noentry)>0) warning('One or more probe sets not found in annotation')

	geneid<-as.list(rep(noIDsymbol,length(ps)))
	geneid[complete.cases(ind)]<-annot[na.omit(ind),idCol]
	
	noid<-geneid==noIDprovidedSymbol
	geneid[noid]<-noIDsymbol 
	if (sum(noid)>0) warning('One or more probe sets with no gene ID provided in annotation')
	
	indMultID<-grep(sep,geneid)
	geneid[indMultID]<-lapply(geneid[indMultID],function(x) {strsplit(x,sep)[[1]]})
	
	if (diagnose) list(geneid,empty,noentry,noid)
	else geneid

}
getGENEONTOLOGY<-function(ps,annot,diagnose=FALSE,specifics=0,GOcol=31,noGOsymbol=NA,noGOprovidedSymbol='---',sep=' /// ') {

	if (!is.element(specifics,0:3)) stop('Argument specifics should be 0, 1, 2, or 3')

	empty<-(is.na(ps) | ps=='')
	ind<-match(ps,annot[,1])
	noentry<-(is.na(ind) & !empty)
	if (sum(empty)>0) warning('One or more empty probe sets in input')
	if (sum(noentry)>0) warning('One or more probe sets not found in annotation')

	go<-as.list(rep(noGOsymbol,length(ps)))
	go[complete.cases(ind)]<-annot[na.omit(ind),GOcol] 

	nogo<-go==noGOprovidedSymbol
	go[nogo]<-noGOsymbol 
	if (sum(nogo)>0) warning('One or more ps with no GO term provided in annotation')
	
	indMultGO<-grep('///',go)
	go[indMultGO]<-lapply(go[indMultGO],function(x) {strsplit(x,sep)[[1]]})

	if (specifics!=0) {
		indGOsymbol<-!empty & !noentry & !nogo
		go[indGOsymbol]<-lapply(go[indGOsymbol],function(x) {unlist(lapply(x, function(x) {strsplit(x,' // ')[[1]][specifics]}))})
	}
	if (diagnose) list(go,empty,noentry,nogo)
	else go

}


getGENESYMBOL<-function(ps,annot,diagnose=FALSE,GScol=15,noGSsymbol=NA,noGSprovidedSymbol='---',sep=' /// ')  {

	if (is.na(noGSprovidedSymbol)) stop('Argument noGSprovidedSymbol should be different from NA')
	if (!(is.na(noGSsymbol))) {if (noGSsymbol==noGSprovidedSymbol) stop('Argument noGSsymbol and noGSprovidedSymbol should be different')}

	empty<-(is.na(ps) | ps=='')
	ind<-match(ps,annot[,1])
	noentry<-(is.na(ind) & !empty)
	if (sum(empty)>0) {cat('Warning: one or more empty probe sets in input\n')}
	if (sum(noentry)>0) {cat('Warning: one or more probe sets not found in annotation\n')}
	
	symbols<-as.list(rep(noGSsymbol,length(ps)))
	symbols[complete.cases(ind)]<-annot[na.omit(ind),GScol]
	
	nogs<-symbols==noGSprovidedSymbol
	symbols[nogs]<-noGSsymbol 
	if (sum(nogs)>0) warning('One or more probe sets with no gene symbol provided in annotation')
	
	indMultGS<-grep(sep,symbols)
	symbols[indMultGS]<-lapply(symbols[indMultGS],function(x) {strsplit(x,sep)[[1]]})

	if (diagnose) list(symbols,empty,noentry,nogs)
	else symbols

}

getGENETITLE<-function(ps,annot,diagnose=FALSE,TITLEcol=14,noTITLEsymbol=NA,noTITLEprovidedSymbol='---',sep=' /// ') {

	if (is.na(noTITLEprovidedSymbol)) stop('Argument noTITLEprovidedSymbol should be different from NA')
	if (!(is.na(noTITLEsymbol))) {if (noTITLEsymbol==noTITLEprovidedSymbol) stop('Argument noTITLEsymbol and noTITLEprovidedSymbol should be different')}
	
	empty<-(is.na(ps) | ps=='')
	ind<-match(ps,annot[,1])
	noentry<-(is.na(ind) & !empty)
	if (sum(empty)>0) warning('One or more empty probe sets in input')
	if (sum(noentry)>0) warning('One or more probe sets not found in annotation')

	genetitle<-as.list(rep(noTITLEsymbol,length(ps)))
	genetitle[complete.cases(ind)]<-annot[na.omit(ind),TITLEcol]
	
	notitle<-genetitle==noTITLEprovidedSymbol
	genetitle[notitle]<-noTITLEsymbol 
	if (sum(notitle)>0) warning('One or more ps with no gene TITLE provided in annotation')
	
	indMultTITLE<-grep(sep,genetitle)
	genetitle[indMultTITLE]<-lapply(genetitle[indMultTITLE],function(x) {strsplit(x,sep)[[1]]})
	genetitle<-lapply(genetitle, function(x) {unique(x)})
	
	if (diagnose) list(genetitle,empty,noentry,notitle)
	else genetitle

}



getHOMOLOG<-function(geneid,targetspecies,homol,cluster=FALSE,diagnose=FALSE,noIDsymbol=NA,clusterCol=1,speciesCol=2,idCol=3) {
	
	empty<-(is.na(geneid) | geneid=='')
	if (sum(empty)>0) warning('One or more empty gene ID/cluster in input')	

	if (!cluster) {
	indgeneid<-match(geneid,homol[,idCol])
	cluster<-homol[indgeneid,clusterCol]
	}	
	else {
	indgeneid<-match(geneid,homol[,clusterCol])
	cluster<-geneid	
	}

	noentry<-(is.na(indgeneid) & !empty)
	if (sum(noentry)>0) warning('One or more gene input gene ID/cluster not found in homologue table')

	targetid<-as.list(rep(noIDsymbol,length(geneid)))
	indtargetspecies<-homol[,speciesCol]==targetspecies
	ind<-which(!empty & !noentry)
	for (i in 1:sum(!empty & !noentry)) {
		targetid[[ind[i]]]<-homol[which(homol[,clusterCol]==cluster[ind[i]] & indtargetspecies),idCol]
	}

	targetidnb<-sapply(targetid,function(x) {length(x)})
	notargetid<-targetidnb==0
	if (sum(notargetid)>0) warning('One or more gene ID/cluster with no target provided in homologue table')

	targetid[noentry | notargetid]<-noIDsymbol

	if (diagnose) list(targetid,empty,noentry,notargetid)
	else targetid


}
getMULTIANNOTATION<-function(identifier,annot,diagnose=FALSE,identifierCol=19,annotationCol=1,noAnnotationSymbol=NA,noAnnotationProvidedSymbol='---') {

	if (is.na(noAnnotationProvidedSymbol)) stop('Argument noAnnotationProvidedSymbol should be different from NA')
	if (!(is.na(noAnnotationSymbol))) {if (noAnnotationSymbol==noAnnotationProvidedSymbol) stop('Argument noAnnotationSymbol and noAnnotationProvidedSymbol should be different')}

	empty<-(is.na(identifier) | identifier=='')
	if (sum(empty)>0) warning('one or more empty ID in input')

	if (sum(empty)==length(empty)) {ps<-as.list(rep(NA,length(empty))); noentry<-rep(FALSE,length(empty)); nops<-rep(FALSE,length(empty))}
	else {
		annotation<-as.list(rep(noAnnotationSymbol,length(identifier)))

		ind<-which(!empty)
		for (i in 1:sum(!empty)) {
			annotation[[ind[i]]]<-annot[which(annot[,identifierCol]==identifier[ind[i]]),annotationCol]
		}

		annotationnb<-sapply(annotation,function(x) {length(x)})
		noentry<-annotationnb==0
		if (sum(noentry)>0) warning('one or more ID not found in annotation')

		noannotation<-annotation==noAnnotationProvidedSymbol
		if (sum(noannotation)>0) warning('One or more ID with no annotation provided in annotation')

		annotation[noentry | noannotation]<-noAnnotationSymbol
	}
	if (diagnose) list(annotation,empty,noentry,noannotation)
	else annotation

}


getOrthologousProbesets<-function(ps1,ps2,ps2ps,fct=function(x){x},forceProbesetSelection=FALSE) {


	ps1_length<-length(ps1)
	ps2_ind<-as.list(rep(NA,ps1_length))
	ps2_probe<-as.list(rep(NA,ps1_length))
	ps2_probeSel<-as.list(rep(NA,ps1_length))
	ps2_value<-as.list(rep(NA,ps1_length))
	

	ps2_probe<-ps2ps[match(ps1,ps2ps[,1]),4]
	ps2_orthoFound<-!is.na(ps2_probe)
	ps2_probe<-lapply(ps2_probe,function(x){strsplit(x,',')[[1]]})
	

	ps2_ind[ps2_orthoFound]<-lapply(ps2_probe[ps2_orthoFound],function(x){na.omit(match(x,ps2[,1]))})
	ps2_orthoFoundandExisting<-!is.na(ps2_ind)


	ps2_value[ps2_orthoFoundandExisting]<-lapply(ps2_ind[ps2_orthoFoundandExisting],function(x){ps2[x,2]})
	ps2_value[ps2_orthoFoundandExisting]<-lapply(ps2_value[ps2_orthoFoundandExisting],fct)

	if (!forceProbesetSelection) ps2_probeSel[ps2_orthoFoundandExisting]<-lapply(ps2_ind[ps2_orthoFoundandExisting],function(x){ps2[x,1]})

	else {
		for (i in (1:ps1_length)[ps2_orthoFoundandExisting]) {
			ps2_probeSel[[i]]<-ps2[ps2_ind[[i]][na.omit(match(ps2_value[[i]],ps2[ps2_ind[[i]],2]))],1]
		}
	}
	
	list(ps2_probeSel,ps2_value)

}

getPROBESET<-function(geneid,annot,uniqueID=FALSE,diagnose=FALSE,idCol=19,noPSsymbol=NA,noPSprovidedSymbol='---') {

	if (is.na(noPSprovidedSymbol)) stop('Argument noPSprovidedSymbol should be different from NA')
	if (!(is.na(noPSsymbol))) {if (noPSsymbol==noPSprovidedSymbol) stop('Argument noPSsymbol and noPSprovidedSymbol should be different')}

	empty<-(is.na(geneid) | geneid=='')
	if (sum(empty)>0) warning('one or more empty gene ID in input')

	if (sum(empty)==length(empty)) {ps<-as.list(rep(NA,length(empty))); noentry<-rep(FALSE,length(empty)); nops<-rep(FALSE,length(empty))}
	else {
		ps<-as.list(rep(noPSsymbol,length(geneid)))

		if (uniqueID) pat<-paste('^',geneid,'$',sep='')
		else pat<-paste('(^| )',geneid,'($| )',sep='')

		ind<-which(!empty)
		for (i in 1:sum(!empty)) {
			ps[[ind[i]]]<-annot[grep(pat[ind[i]],annot[,idCol]),1]
		}

		psnb<-sapply(ps,function(x) {length(x)})
		noentry<-psnb==0
		if (sum(noentry)>0) warning('one or more gene ID not found in annotation')

		nops<-ps==noPSprovidedSymbol
		if (sum(nops)>0) warning('One or more gene ID with no probe set provided in annotation')

		ps[noentry | nops]<-noPSsymbol
	}
	if (diagnose) list(ps,empty,noentry,nops)
	else ps
	
}


listToCharacterVector<-function(lst,sep=' /// ') {

	isna<-is.na(lst)
	v<-rep(NA,length(lst))
	if (sum(isna)!=length(isna)) v[!isna]<-sapply(lst[!isna],function(x) {paste(x,collapse=sep)})
	v	
}
ps2ps<-function(annotation_1,annotation_2,homologene,target_species,probesets=NULL) {
	
	if (is.null(probesets)) ps_1<-annotation_1[,1]
	else ps_1<-probesets
	cat('Getting source gene IDs...\n')
	gid_1<-getGENEID(ps_1,annotation_1)
	length_gid_1<-sapply(gid_1,function(x) {length(x)})
	cat('Getting orthologous genes...\n')
	gid_2<-getHOMOLOG(unlist(gid_1),target_species,homologene)
	length_gid_2<-sapply(gid_2,function(x) {length(x)})
	cat('Getting orthologous probe sets...\n')
	ps_2<-getPROBESET(unlist(gid_2),annotation_2)
	
	ps_2_1<-compactList(ps_2,length_gid_2)
	ps_2_2<-compactList(ps_2_1,length_gid_1)
	gid_2_1<-compactList(gid_2,length_gid_1)

	ps_2_2<-lapply(ps_2_2,function(x) {unique(x)})
	ps_2_2<-lapply(ps_2_2,function(x) {if (length(x)>1) na.omit(x) else x})
	gid_2_1<-lapply(gid_2_1,function(x) {unique(x)})
	gid_2_1<-lapply(gid_2_1,function(x) {if (length(x)>1) na.omit(x) else x})

	mappingTable<-data.frame(ps_1=I(ps_1),gid_1=I(listToCharacterVector(gid_1,sep=',')),gid_2=I(listToCharacterVector(gid_2_1,sep=',')),ps_2=I(listToCharacterVector(ps_2_2,sep=',')))
	mappingTable

}
.First.lib <- function(lib, pkg) {
if(.Platform$OS.type == "windows" && require(Biobase) && interactive()  && .Platform$GUI == "Rgui") {
	addVigs2WinMenu("annotationTools")
	}

}
