package org.fda.evaluator;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import org.fda.alignment.ScaffoldContig;
import org.fda.data.ReferenceSet;
import org.fda.data.Utilities;

/**
 *
 * @author Gokhan.Yavas
 */
public class Reevaluator extends EvaluatorBase{
    public Reevaluator(File sourceFolder,  File outdir, ReferenceSet chrset, File modfile) throws IOException{        
        super(sourceFolder,outdir, chrset);
        File tmpContigFile = new File(sourceFolder.getAbsolutePath()+File.separator+Utilities.contigBinFileName);
        
        // overwrite the current folder
        if(this.outdir==null){
            this.outdir = sourceFolder;                            
            writeToDest=false;
        }
        else{
            this.outdir.mkdirs();
            // create the sub directories
            File tmpdir;
            for(String d: Utilities.sub_dirs){
                tmpdir = new File(this.outdir.getAbsolutePath()+File.separator+d);
                tmpdir.mkdirs();
            }
            if(new File(this.sourceFolder+File.separator+Utilities.assemblystatsFile).exists()){                
                Files.copy(new File(this.sourceFolder+File.separator+Utilities.assemblystatsFile).toPath(), new File(this.outdir+File.separator+Utilities.assemblystatsFile).toPath(), StandardCopyOption.REPLACE_EXISTING);
            }
            if(new File(this.sourceFolder+File.separator+Utilities.chrGapsFileName).exists()){                
                Files.copy(new File(this.sourceFolder+File.separator+Utilities.chrGapsFileName).toPath(), new File(this.outdir+File.separator+Utilities.chrGapsFileName).toPath(), StandardCopyOption.REPLACE_EXISTING);
            }
            
        }
        Files.copy(modfile.toPath(), new File(this.outdir+File.separator+Utilities.modelFileName).toPath(), StandardCopyOption.REPLACE_EXISTING);
        
        contigfile = tmpContigFile;
        outfile = new File(this.outdir.getAbsolutePath()+File.separator+Utilities.contigsStats);
        alignmentfile = new File(this.outdir.getAbsolutePath()+File.separator+Utilities.alignmentFile);
        missassemblyFile = new File(outdir.getAbsolutePath()+File.separator+Utilities.misassemblyFile);
        p = new Processor(this, chrset, outdir);
    }
    
    @Override
    public QLPair[] process(){
        ObjectOutputStream outstream=null;
        ObjectInputStream instream = null;
        
        QLPair[] quallist=null;
        //double maxInconsistency=0;
        try {
            ScaffoldContig als;

            // open the already existing file and re-assign the confidence and then write it to another file
            File tmpfile;
            if(sourceFolder.equals(outdir)){
                tmpfile = new File(contigfile.getAbsolutePath()+".tmp");
                tmpfile.deleteOnExit();
                Files.move(contigfile.toPath(), tmpfile.toPath(), StandardCopyOption.ATOMIC_MOVE);                
            }
            else{
                tmpfile = contigfile;
                contigfile = new File(outdir.getAbsolutePath()+File.separator+Utilities.contigBinFileName);
                Files.copy(new File(sourceFolder.getAbsolutePath()+ File.separator + Utilities.chrStatFileName).toPath(),
                    new File(outdir.getAbsolutePath()+ File.separator + Utilities.chrStatFileName).toPath(),StandardCopyOption.REPLACE_EXISTING);
            }
            outstream = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(contigfile)));
            instream = new ObjectInputStream(new BufferedInputStream(new FileInputStream(tmpfile)));
            int contigNumber = instream.readInt();
            outstream.writeInt(contigNumber);
            quallist = new QLPair[contigNumber];
            int indx=0;
            while(true){
                als = (ScaffoldContig)instream.readObject();
                als.assignQuality();
                p.process(als);                                
                //maxInconsistency = Math.max(als.getTotalInconsistency(), maxInconsistency);
                outstream.writeObject(als);
                bw.append(als.toString(false));
                bwc.append(als.toString(true));
                if(als.getIsMisassembled() || als.containsScaffoldingGap())
                    misassemblyBw.append(als.getString4Misassemblies());
                //quallist[indx]=als.getQuality();
                quallist[indx]=new QLPair(als.getContigLength(), als.getQuality());
                indx++;
            }            
        }
        catch(ClassNotFoundException e){e.printStackTrace();}
        catch (IOException ex) {
            if(!(ex instanceof EOFException))
                ex.printStackTrace();
        }            
        finally {
            try {
                outstream.close();
                instream.close();
//                bw.close();
            } catch (IOException ex) {
                ex.printStackTrace();                    
            }
        }        
        return quallist;
    }
}
