package prok;

import java.util.ArrayList;
import java.util.HashSet;

import fileIO.FileFormat;
import fileIO.TextStreamWriter;
import server.ServerTools;
import shared.Tools;
import template.ThreadWaiter;

public class FetchProks {
	
	public static void main(String[] args){
		//ftp://ftp.ncbi.nih.gov:21/genomes/refseq/bacteria/
		
		String baseAddress=args[0];
		String out=args.length>1 ? args[1] : "stdout";
		if(args.length>2){
			allowSameGenus=Tools.parseBoolean(args[2]);
			System.err.println("Set allowSameGenus="+allowSameGenus);
		}
		TextStreamWriter tsw=new TextStreamWriter(out, true, false, false, FileFormat.TEXT);
		tsw.start();

//		iterateOuter(baseAddress, tsw);
		ArrayList<String> contents=ServerTools.listDirectory(baseAddress);
		
		int threads=16;
		ArrayList<ProcessThread> alpt=new ArrayList<ProcessThread>(threads);
		for(int i=0; i<threads; i++){
			alpt.add(new ProcessThread(contents, tsw, i, threads));
		}
		for(ProcessThread pt : alpt){pt.start();}
		boolean success=ThreadWaiter.waitForThreads(alpt);
		
		tsw.poisonAndWait();
		assert(success);
	}
	
	static class ProcessThread extends Thread {
		
		ProcessThread(ArrayList<String> speciesList_, TextStreamWriter tsw_, int tid_, int threads_){
			speciesList=speciesList_;
			tsw=tsw_;
			tid=tid_;
			threads=threads_;
		}
		
		@Override
		public void run(){
			for(String s : speciesList){
				char c=s.charAt(0);
				if(c%threads==tid) {
					processSpecies(s);
				}
			}
		}
		
		void processSpecies(String species){
			String genus=getGenus(species);
			if(genus!=null){
				if(allowSameGenus || !seen.contains(genus)){
					seen.add(genus);
					examineSpecies(species, tsw);
				}else{
					if(verbose){System.err.println("same genus: "+species+"\n"+genus);}
				}
			}else{
				if(verbose){System.err.println("bad species: "+species+"\n"+genus);}
			}
		}
		
		final ArrayList<String> speciesList;
		final int tid;
		final int threads;
		final HashSet<String> seen=new HashSet<String>();
		final TextStreamWriter tsw;
	}
	
	static void iterateOuter(String baseAddress, TextStreamWriter tsw){
		ArrayList<String> contents=ServerTools.listDirectory(baseAddress);
		
		HashSet<String> seen=new HashSet<String>();
		for(String species : contents){
//			System.err.println(species);
			String genus=getGenus(species);
			if(genus!=null){
				if(!seen.contains(genus) || allowSameGenus){
					seen.add(genus);
					examineSpecies(species, tsw);
				}else{
					if(verbose){System.err.println("same genus: "+species+"\n"+genus);}
				}
			}else{
				if(verbose){System.err.println("bad species: "+species+"\n"+genus);}
			}
		}
	}
	
	static String getGenus(String path){
		//Candidatus_Hamiltonella
		String name=path.substring(path.lastIndexOf('/')+1);
		if(name.startsWith("Candidatus_")){name=name.substring("Candidatus_".length());}
		int under=name.indexOf('_');
		if(under>0){
			return name.substring(0, under);
		}else{
			return null;
		}
	}
	
	static void examineSpecies(String baseAddress, TextStreamWriter tsw){
		if(verbose){System.err.println("examineSpecies: "+baseAddress);}
		ArrayList<String> contents=ServerTools.listDirectory(baseAddress);
//		System.err.println("B: "+contents);
		for(String s : contents){
//			System.err.println(s);
			if(s.contains("latest_assembly_versions")){
//				System.err.println("Looking at '"+s+"'");
				examineAssemblies(s, tsw);
			}
		}
	}
	
	static void examineAssemblies(String baseAddress, TextStreamWriter tsw){
		if(verbose){System.err.println("examineAssemblies: "+baseAddress);}
		ArrayList<String> contents=ServerTools.listDirectory(baseAddress);
//		System.err.println("C: "+contents);
		for(String s : contents){
//			System.err.println(s);
			examineAssembly(s, tsw);
			break;
		}
	}
	
	static void examineAssembly(String baseAddress, TextStreamWriter tsw){
		if(verbose){System.err.println("examineAssembly: "+baseAddress);}
		ArrayList<String> contents=ServerTools.listDirectory(baseAddress);
//		System.err.println("D: "+contents);
		String gff=null;
		String fna=null;
		for(String s : contents){
//			System.err.println(s);
			if(!s.contains("_from_genomic")){
				if(s.endsWith("genomic.fna.gz")){fna=s;}
				else if(s.endsWith("genomic.gff.gz")){gff=s;}
			}
		}
		if(fna!=null && gff!=null){
			System.err.println("Printing: "+fna);
//			System.err.println(fna);
			synchronized(tsw){
				tsw.println("wget -q "+fna);
				tsw.println("wget -q "+gff);
				tsw.println();
			}
			
		}
	}
	
	static String makeSubAddress(String baseAddress, String extension){
		if(!baseAddress.endsWith("/")){baseAddress=baseAddress+"/";}
		String subAddress=baseAddress+extension.substring(extension.indexOf('/')+1);
		return subAddress;
	}
	
	static boolean verbose=true;
	static boolean allowSameGenus=false;
	
}
