package skyview.survey;

import skyview.survey.XMLSurvey;
import skyview.executive.Settings;

import java.io.File;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.FilenameFilter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.nio.file.Paths;
import java.nio.file.Path;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
import java.util.regex.Pattern;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;


/** This class provides functionality to translate survey
 *  names into associated survey description files.
 * @author tmcglynn
 */
public class SurveyExtractor  {
    
    /** Default location for survey manifest */
    private static String  	defaultSurveyManifest = "survey.manifest";
    Writer sw;

    
    /** Filter to get only the XML files */
    private FilenameFilter 	filter = new FilenameFilter() {
	public boolean accept(File file, String name) {
	    return name.endsWith(".xml") || name.endsWith(".XML");
	}
    };
    
    /** Hashmap binding shortname to XML file */
    private HashMap<String,String> hash = new HashMap<String,String>();

    /** Set up the SurveyFinder and populate the map */
    public SurveyExtractor() throws Exception {
	
        sw = new OutputStreamWriter(System.out);
	getSurveysFromManifest();  // Must be done first since it may reset hash.
	getSurveysFromRoot();
	getSurveysFromUser();
        sw.close();

    }
        
    /** Get the surveys in the document root area */
    protected void getSurveysFromRoot() {
	
	String[] roots = Settings.getArray("xmlroot");
	
        for (String root: roots) {
	    File     f      = new File(root);
	    String[] match  = f.list(filter);
	
	    for (String survey: match) {
	        process(root+"/"+survey);
	    }
	}
    }
    
    /** Get user specified surveys */
    protected void getSurveysFromUser() {
	
	String userSurveys= Settings.get("surveyxml");
	if (userSurveys != null) {
	    
	    Pattern comma    = Pattern.compile(",");
	    String[] surveys = comma.split(userSurveys);
	    for (int i=0; i<surveys.length; i += 1) {
		process(surveys[i]);
	    }
	}
    }

    /** Get surveys from a user manifest.  This
     *  is how SkyView-in-a-Jar gets its surveys.
     */
    protected void getSurveysFromManifest() {
	
	try {
	    String manifest = Settings.get("surveymanifest");
	    if (manifest == null) {
		manifest = defaultSurveyManifest;
	    }
            
	    InputStream is = skyview.survey.Util.getResourceOrFile(manifest);
	    if (is == null) {
		return;
	    }
	    BufferedReader br = new BufferedReader(new InputStreamReader(is));
	    String survey;
	    while ( (survey = br.readLine() ) != null) {
		survey=survey.trim();
		if (survey.length() == 0 || survey.charAt(0) == '#') {
		    continue;
		}
                
		process(survey);
	    }
	    
	} catch (Exception e) {
	    System.err.println("Error loading surveys from manifest: "+e+"\n Processing continues");
	    // Continue with whatever surveys have already been loaded.
	}
    }
							     


    /** Parse a single file */
    private void process(String name) {
        String prefix;
	Path prefixPath;
	try {
	    File jarFile = new File(SurveyExtractor.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
	    prefix = jarFile.getParentFile().getPath();
	} catch(Exception e){
	    throw new Error("Unable to determine path to file:  "+e);
        }

	try {
	   prefixPath = Paths.get(prefix);
	   String xmlSourceFile=prefixPath.resolve(name).toString();
	   Source xmlSource = new StreamSource(XMLSurvey.getSurveyReader(xmlSourceFile));
           String xslFile = Settings.get("SurveyXSLT");
           if (xslFile == null) {
               xslFile = "survey.xslt";
           }
	   Source xslSource = new StreamSource(xslFile);
           
	
	   Result output    = new StreamResult(sw);
	   Transformer trans= TransformerFactory.newInstance().newTransformer(xslSource);
	   trans.transform(xmlSource, output);
	    
	} catch (Exception e) {
	    e.printStackTrace(System.err);
	    throw new Error("Unexpected exception parsing file: "+name+" in SurveyFinder:"+e);
	    
	}
        
    }
        
    public static void main(String[] args) throws Exception {
        Settings.addArgs(args);
        System.out.println("Name,F,Fmin,Fmax,MJD,MJDmin,MJDmax,Coverage,Resolution,Scale,Sensitivity");
        new SurveyExtractor();
    }
}
