package org.bbop.apollo.sequence.search.blast;

import org.bbop.apollo.sequence.search.AlignmentParsingException;
import org.bbop.apollo.sequence.search.SequenceSearchTool;
import org.bbop.apollo.sequence.search.SequenceSearchToolException;
import org.bbop.apollo.sequence.search.blast.BlastAlignment;
import org.bbop.apollo.sequence.search.blast.TabDelimittedAlignment;
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.codehaus.groovy.grails.web.json.JSONObject;

public class BlastCommandLine extends SequenceSearchTool {

    private String blastBin;
    private String database;
    private String blastUserOptions;
    private String tmpDir;
    private boolean removeTmpDir;
    protected String [] blastOptions;
    
    @Override
    public void parseConfiguration(JSONObject config) throws SequenceSearchToolException {
        try {
            if(config.has("search_exe")) { blastBin = config.getString("search_exe"); }
            else { throw new SequenceSearchToolException("No blast exe specified"); }
            if(config.has("database")&&config.getString("database")!="") {database = config.getString("database"); }
            else { throw new SequenceSearchToolException("No database configured"); }
            if(config.has("params")) {blastUserOptions = config.getString("params");}
            else { /* no extra params needed */ }
            if(config.has("removeTmpDir")) {removeTmpDir=config.getBoolean("removeTmpDir"); }
            else { removeTmpDir=true; }
            if(config.has("tmp_dir")) {tmpDir=config.getString("tmp_dir"); }
        } catch (Exception e) {
            throw new SequenceSearchToolException("Error parsing configuration: " + e.getMessage(), e);
        }
    }


    @Override
    public Collection<BlastAlignment> search(String uniqueToken, String query, String databaseId) throws SequenceSearchToolException {
        File dir = null;
        Path p = null;
        try {
            if(tmpDir==null) {
                p = Files.createTempDirectory("blast_tmp");
            }
            else {
                p = Files.createTempDirectory(new File(tmpDir).toPath(),"blast_tmp");
            }
            dir = p.toFile();

            return runSearch(dir, query, databaseId);
        }
        catch (IOException e) {
            throw new SequenceSearchToolException("Error running search: " + e.getMessage(), e);
        }
        catch (AlignmentParsingException e) {
            throw new SequenceSearchToolException("Alignment parsing error: " + e.getMessage(), e);
        }
        catch (InterruptedException e) {
            throw new SequenceSearchToolException("Error running search: " + e.getMessage(), e);
        }
        finally {
            if (removeTmpDir && dir!=null) {
                deleteTmpDir(dir);
            }
        }
    }
    
    private Collection<BlastAlignment> runSearch(File dir, String query, String databaseId)
            throws IOException, AlignmentParsingException, InterruptedException {
        PrintWriter log = new PrintWriter(new BufferedWriter(new FileWriter(dir + "/search.log")));
        String queryArg = createQueryFasta(dir, query);
        String databaseArg = database + (databaseId != null ? ":" + databaseId : "");
        String outputArg = dir.getAbsolutePath() + "/results.tab";
        List<String> commands = new ArrayList<String>();
        commands.add(blastBin);
        System.out.println( blastBin);
        if (blastOptions != null) {
            for (String option : blastOptions) {
                commands.add(option);
                System.out.println(option);
            }
        }
        commands.add("-db "+databaseArg);
        commands.add("-query " + queryArg);
        commands.add("-out "+outputArg);
        commands.add("-outfmt 6");
        if (blastUserOptions != null && blastUserOptions.length() > 0) {
            for (String option : blastUserOptions.split("\\s+")) {
                commands.add(option);
            }
        }
        log.println("Command:");
        for (String arg : commands) {
            log.print(arg + " ");
        }
        ProcessBuilder pb = new ProcessBuilder(commands);
        Process p = pb.start();
        p.waitFor();
        String line;
        BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
        log.println("stdout:");
        while ((line = stdout.readLine()) != null) {
            log.println(line);
        }
        log.println();
        BufferedReader stderr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        log.println("stderr:");
        while ((line = stderr.readLine()) != null) {
            log.println(line);
        }
        log.close();
        p.destroy();
        Collection<BlastAlignment> matches = new ArrayList<BlastAlignment>();
        BufferedReader in = new BufferedReader(new FileReader(outputArg));
        while ((line = in.readLine()) != null) {
            matches.add(new TabDelimittedAlignment(line));
        }
        in.close();
        return matches;
    }

    private void deleteTmpDir(File dir) {
        if (!dir.exists()) {
            return;
        }
        for (File f : dir.listFiles()) {
            f.delete();
        }
        dir.delete();
    }


    private String createQueryFasta(File dir, String query) throws IOException {
        String queryFileName = dir.getAbsolutePath() + "/query.fa";
        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(queryFileName)));
        out.println(">query");
        out.println(query);
        out.close();
        return queryFileName;
    }
    
}

@@ -3685,51 +3685,18 @@
     
-    System.out.println(option);%0A   
+%7D%0A
         
  %7D%0A 
@@ -3683,33 +3683,32 @@
       %7D%0A        
- 
 %7D%0A        %7D%0A    
@@ -3693,33 +3693,52 @@
       %7D%0A        
-%7D
+commands.add(%22-db%22);
 %0A        command
@@ -3747,15 +3747,8 @@
 add(
-%22-db %22+
 data
@@ -3785,21 +3785,41 @@
 (%22-query
- %22 + 
+%22);%0A        commands.add(
 queryArg
@@ -3851,11 +3851,33 @@
 -out
- %22+
+%22);%0A        commands.add(
 outp
@@ -3913,17 +3913,42 @@
 %22-outfmt
- 
+%22);%0A        commands.add(%22
 6%22);%0A   
@@ -4253,32 +4253,34 @@
 %22 %22);%0A        %7D%0A
+%0A%0A
         ProcessB

Fix the processbuilder on the BLAST plugin