
package org.fda.multithreading;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.BlockingQueue;
import org.fda.alignment.ScaffoldContig;
import org.fda.basicstats.ContigRecord;
import org.fda.data.Enums;
import org.fda.data.Enums.STOPOBJECT;
import org.fda.data.Utilities;
import org.fda.evaluator.Processor;

/**
 *
 * @author Gokhan.Yavas
 */
public class StandaloneContigAlignmentQueueMonitor implements Runnable{
    private BlockingQueue queue;    
    private ObjectOutputStream out=null;
    private BufferedWriter bw;
    private BufferedWriter bwc;
    private int contigCount=0;    
    private File sourceFolder;
    private Processor p;
    

    public int getContigCount() {
        return contigCount;
    }
    
    public StandaloneContigAlignmentQueueMonitor(BlockingQueue queue, File contigbinfile, File outputfile, File sourceFolder, Processor p){
        this.queue = queue;
        this.sourceFolder = sourceFolder;
        this.p = p;
        bwc=null;
        try{
            out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(contigbinfile)));
            bw = new BufferedWriter(new FileWriter(outputfile));
            bw.append("Contig ID\tContig Size\tAligned Contig Size\tAlignment Percentage\tGC Ratio\tAmbiguous Base (N) Ratio\tQuality Score");                
            for(Enums.Inconsistency nci: Enums.Inconsistency.values())
                bw.append("\t"+nci);
            bw.append(Utilities.ls);            
        }
        catch(IOException io){io.printStackTrace();}
    }
    public StandaloneContigAlignmentQueueMonitor(BlockingQueue queue, File contigbinfile, BufferedWriter bw, File sourceFolder, BufferedWriter bwc, Processor p){
        this.queue = queue;
        this.sourceFolder = sourceFolder;
        this.bw = bw;
        this.bwc = bwc;
        this.p = p;
        try{
            out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(contigbinfile)));
        }
        catch(IOException io){io.printStackTrace();}
    }
    

    @Override
    public void run() {
        Object o;
        // Now read the whole set of contigs and         
        ObjectInputStream input=null;
        Map<String, ContigRecord> contigs=null;
        ScaffoldContig as;
        try{
            input = new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File(sourceFolder.getAbsolutePath()+File.separator+Utilities.contigObjFile))));
            contigs = (Map<String, ContigRecord>)input.readObject();
        }
        catch(ClassNotFoundException | IOException e){e.printStackTrace();}
        finally {
            try {
                input.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        while(true){            
            try {
                o = queue.take();                
                if(o instanceof STOPOBJECT){
                    break;
                }
                else if (o instanceof ScaffoldContig){
                    String id = ((ScaffoldContig)o).getId();
                    if(contigs.containsKey(id)){
                        contigs.remove(id);
                    }
                    out.writeObject(o);                     
                    p.process((ScaffoldContig)o);
                    bw.append(((ScaffoldContig)o).toString(false));
                    bwc.append(((ScaffoldContig)o).toString(true));

                    contigCount++;
                }                                                   
            } 
            catch(Exception io){ io.printStackTrace();}
        }
        
        // Now create null AlignmentSets for the unaligned ones
        try{
            for(Entry<String, ContigRecord> ent : contigs.entrySet()){
                ContigRecord cr = ent.getValue();
                as = new ScaffoldContig(cr.getContigName(), cr.getLength(), cr.getNCount(), cr.getGCCount(), cr.getGapIntervals());
                as.setHashValue(cr.getHashValue());
                as.setSeqHashValue(cr.getSeqHashValue());
                bw.append(as.toString(false));
                bwc.append(as.toString(true));
                out.writeObject(as);
                contigCount++;
            }
            out.close();
        }
        catch(IOException io){io.printStackTrace();}
        
    }
}
