#!/usr/bin/env bds

#-------------------------------------------------------------------------------
#
# Download a single genome from NCBI
#
#-------------------------------------------------------------------------------

urlNcbiHttp := "https://ftp.ncbi.nlm.nih.gov/"


void downloadNcbiGenome(string genome, string version) {
	if( version.isEmpty() ) error "Error downloading genome '$genome' from NCBI, missing 'genome ID'"
	dg := new DownloadNcbi(genome, version)
	dg.download()
}


class DownloadNcbi extends DownloadGenome {
	string version
	string urlBase
	string assemblyReport
	string chrsIds2Name
	string protIdMap

	# Initialize with genome name and NCBI genome version ID
	# e.g.: new DownloadNcbi('GRCh38.p13', 'GCF_000001405.39')
	void DownloadNcbi(string genome, string version) {
		super.DownloadGenome(genome)
		this.version = version

		# Build a base URL form 'version' and 'genome'
		# The URL look like this: https://ftp.ncbi.nih.gov/genomes/all/GCF/000/001/405/GCF_000001405.39_GRCh38.p13/
		string code, num 
		(code, num) = version.split('_')
		n1 := num.substr(0,3)
		n2 := num.substr(3,6)
		n3 := num.substr(6,9)
		urlBase = "$urlNcbiHttp/genomes/all/$code/$n1/$n2/$n3/$version\_$genome"
		log("Download NCBI: genome '$genome', version: '$version', urlBase: '$urlBase'")

		cdsUrl = "$urlBase/$version\_$genome\_rna.fna.gz"
		fastaUrl = "$urlBase/$version\_$genome\_genomic.fna.gz"
		genesUrl = "$urlBase/$version\_$genome\_genomic.gtf.gz"
		protUrl = "$urlBase/$version\_$genome\_protein.faa.gz"
	}

	string downloadAssemblyReport() {
		arUrl := "$urlBase/$version\_$genome\_assembly_report.txt"
		arLocal := downloadDir + '/' + arUrl.baseName()
		return downloadFile(arUrl, arLocal, "Assembly report", false)
	}

	# Download 'other' necesary files
	# Returns: A list of all paths
	string[] downloadOther() {
		log("Download '$genome': Other")
		assemblyReport = downloadAssemblyReport()
		return [ assemblyReport ]
	}

	# Pre-Process
	void preProcess() {
		log("Pre-Processing '$genome'")
		# Convert assembly report to chrId -> chrName mapping file
		chrsIds2Name = downloadDir + "/chromosomes2name.txt"
		task(chrsIds2Name <- assemblyReport) {
			sys cat "$assemblyReport" | cut -f 1,7 | grep -v "^#" > "$chrsIds2Name"
		}
	}

	# Process CDS file (default, do nothing)
	string processCds(string cds) {
		log("Processing '$genome': CDS file '$cds'")
		cdsFixed := downloadDir + "/cds.fa.gz"
		task(cdsFixed <- [cds, protIdMap]) {
			sys cd "$downloadDir"
			sys gunzip -c "$cds" | perl -pe 's/^>(\\S+).*/>$1/' | gzip -c > "$cdsFixed"
		}
		return cdsFixed
	}

	# Process FASTA file: Fix headers
	string processFasta(string fa) {
		log("Processing '$genome': FASTA file '$fa'")
		faFixed := downloadDir + "/$genome\.fa.gz"
		task(faFixed <- [fa, chrsIds2Name]) {
			sys gunzip -c "$fa" | $dirScriptsBuild/ncbi/fix_fasta.pl "$chrsIds2Name" | gzip -c > "$faFixed"
		}
		return faFixed
		
	}

	# Process genes file
	# Note: It creates 'protein_id.map.txt'
	string processGenes(string genes) {
		log("Processing '$genome': Genes file '$genes'")
		genesFixed := downloadDir + "/genes.gtf.gz"
		protIdMap = downloadDir + "/protein_id.map.txt"
		task([genesFixed, protIdMap] <- [genes, chrsIds2Name]) {
			sys cd "$downloadDir"
			sys $dirScriptsBuild/ncbi/fix_gtf.pl "$genes" "$chrsIds2Name" | gzip -c > "$genesFixed"
		}
		return genesFixed
	}

	# Process protein file: Fix headers
	string processProt(string prot)	{
		log("Processing '$genome': Protein file '$prot'")
		protFixed := downloadDir + "/protein.fa.gz"
		task(protFixed <- [prot, protIdMap]) {
			sys cd "$downloadDir"
			sys gunzip -c "$prot" | $dirScriptsBuild/ncbi/fix_fasta_protein_cds.pl "$protIdMap" | gzip -c > "$protFixed"
		}
		return protFixed
	}
}

