package org.drpowell.varitas;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.net.URL;
import java.util.Scanner;
import java.util.logging.Logger;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.drpowell.tabix.TabixReader;
import org.drpowell.vcf.VCFHeaders;
import org.drpowell.vcf.VCFIterator;
import org.drpowell.vcf.VCFVariant;

public class JavascriptConfiguredAnnotator implements VCFIterator {
	private VCFIterator variants;
	private static Logger logger = Logger.getLogger("Varitas");
	
	private File configFile;
	private File configParent;

	public JavascriptConfiguredAnnotator(VCFIterator client, String configFileName) {
		this.variants = client;
		try {
			initialize(configFileName);
		} catch (IOException ioe) {
			logger.severe(String.format("Error reading config file ( %s ), will make best effort to proceed: %s", configFileName, ioe));
			ioe.printStackTrace();
		} catch (ScriptException se) {
			logger.severe(String.format("Error running config script ( %s ), will make best effort to proceed: %s", configFileName, se));
			se.printStackTrace();
		}
	}
	
	protected void initialize(String configFileName) throws IOException, ScriptException {
		configFile = new File(configFileName);
		configParent = configFile.getParentFile();
		readConfigFromJS(new BufferedReader(new FileReader(configFile)));
	}
	
	private JavascriptConfiguredAnnotator readConfigFromJS(Reader jsReader) throws ScriptException {
		ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
		Scanner s = new Scanner(jsReader);
		String jsString = s.useDelimiter("\\A").next();
		s.close();
		engine.put("__varitas", this);
		engine.eval("with (__varitas) {" + jsString + "}");
		return this;
	}
	
	public GeneAnnotator geneAnnotator(String id, String fileName) {
		URL url = Main.findExistingFile(fileName, configParent);
		try {
			GeneAnnotator annotator = new GeneAnnotator(id, url);
			variants = new AnnotatingIterator(variants, annotator);
			return annotator;
		} catch (IOException ioe) {
			ioe.printStackTrace();
			logger.severe("Unable to read file '" + fileName + "':\n" + ioe.toString());
		}
		return null;
	}
	
	public SnpEffAnnotationSplitter snpEffSplitter() {
		// FIXME -- we really only need one of these, and it should go before any gene annotators
		SnpEffAnnotationSplitter a = new SnpEffAnnotationSplitter();
		variants = new AnnotatingIterator(variants, a);
		return a;
	}

	public TabixVCFAnnotator vcfAnnotator(String fileName, String fieldString) {
		URL url = Main.findExistingFile(fileName, configParent);
		if (url == null) {
			logger.severe("Unable to read file '" + fileName + "'");
			return null;
		}
		try {
			TabixVCFAnnotator annotator = new TabixVCFAnnotator(new TabixReader(url.getFile()), fieldString);
			variants = new AnnotatingIterator(variants, annotator);
			return annotator;
		} catch (IOException e) {
			e.printStackTrace();
			logger.severe("Unable to read file '" + fileName + "':\n" + e.toString());
		}
		return null;
	}

	public TabixTSVAnnotator tsvAnnotator(String fileName, String fieldString) {
		URL url = Main.findExistingFile(fileName, configParent);
		if (url == null) {
			logger.severe("Unable to read file '" + fileName + "'");
			return null;
		}
		try {
			TabixTSVAnnotator annotator = new TabixTSVAnnotator(new TabixReader(url.getFile()), fieldString);
			variants = new AnnotatingIterator(variants, annotator);
			return annotator;
		} catch (IOException ioe) {
			ioe.printStackTrace();
			logger.severe("Unable to read file '" + fileName + "':\n" + ioe.toString());
		}
		return null;
	}

	@Override
	public boolean hasNext() {
		return variants.hasNext();
	}

	@Override
	public VCFVariant next() {
		return variants.next();
	}

	@Override
	public void remove() {
		variants.remove();
	}

	@Override
	public VCFHeaders getHeaders() {
		return variants.getHeaders();
	}

}

@@ -76,16 +76,54 @@
 o.File;%0A
+import java.io.FileNotFoundException;%0A
 import j
@@ -533,16 +533,123 @@
 Variant;
+%0Aimport org.drpowell.vcffilters.JavascriptBooleanVCFFilter;%0Aimport org.drpowell.vcffilters.ScriptVCFFilter;
 %0A%0Apublic
@@ -3883,24 +3883,572 @@
 urn null;%0A%09%7D
+%0A%09%0A%09public ScriptVCFFilter applyFilter(String filename) %7B%0A%09%09try %7B%0A%09%09%09ScriptVCFFilter filter = new ScriptVCFFilter(variants, new FileReader(filename));%0A%09%09%09variants = filter;%0A%09%09%09return filter;%0A%09%09%7D catch (FileNotFoundException e) %7B%0A%09%09%09e.printStackTrace();%0A%09%09%09logger.severe(%22Unable to read file '%22 + e + %22', will ignore this filter:%5Cn%22 + e.toString());%0A%09%09%7D%0A%09%09return null;%0A%09%7D%0A%09%0A%09public JavascriptBooleanVCFFilter jsBoolean(String filter) %7B%0A%09%09JavascriptBooleanVCFFilter f = new JavascriptBooleanVCFFilter(variants, filter);%0A%09%09variants = f;%0A%09%09return f;%0A%09%7D
 %0A%0A%09@Override

allow filters to be constructed with JavascriptConfiguredAnnotator