/*
 *                    BioJava development code
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  If you do not have a copy,
 * see:
 *
 *      http://www.gnu.org/copyleft/lesser.html
 *
 * Copyright for this code is held jointly by the individual
 * authors.  These should be listed in @author doc comments.
 *
 * For more information on the BioJava project and its aims,
 * or to join the biojava-l mailing list, visit the home page
 * at:
 *
 *      http://www.biojava.org/
 *
 * Created on 01-21-2010
 */
package org.biojava.nbio.core.sequence.io;

import org.biojava.nbio.core.sequence.DNASequence;
import org.biojava.nbio.core.sequence.GeneSequence;
import org.biojava.nbio.core.sequence.ProteinSequence;
import org.biojava.nbio.core.sequence.compound.AminoAcidCompound;
import org.biojava.nbio.core.sequence.compound.NucleotideCompound;
import org.biojava.nbio.core.sequence.io.template.FastaHeaderFormatInterface;
import org.biojava.nbio.core.sequence.template.Compound;
import org.biojava.nbio.core.sequence.template.Sequence;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;

/**
 * The class that should be used to write out fasta file of a sequence collection
 * @author Scooter Willis <willishf at gmail dot com>
 */
public class FastaWriterHelper {



    /**
     * Write collection of protein sequences to a file
     *
     * @param file
     * @param proteinSequences
     * @throws Exception
     */
    public static void writeProteinSequence(File file,
            Collection<ProteinSequence> proteinSequences) throws Exception {
        FileOutputStream outputStream = new FileOutputStream(file);
        BufferedOutputStream bo = new BufferedOutputStream(outputStream);
        writeProteinSequence(bo, proteinSequences);
        bo.close();
        outputStream.close();
    }

    /**
     * Write collection of protein sequences to a stream
     * @param outputStream
     * @param proteinSequences
     * @throws Exception
     */

    public static void writeProteinSequence(OutputStream outputStream,
            Collection<ProteinSequence> proteinSequences) throws Exception {

        FastaWriter<ProteinSequence, AminoAcidCompound> fastaWriter = new FastaWriter<ProteinSequence, AminoAcidCompound>(
                outputStream, proteinSequences,
                new GenericFastaHeaderFormat<ProteinSequence, AminoAcidCompound>());
        fastaWriter.process();

    }

        /**
     * Write a collection of GeneSequences to a file where if the gene is negative strand it will flip and complement the sequence
     * @param file
     * @param geneSequences
     * @throws Exception
     */

    public static void writeGeneSequence(File file, Collection<GeneSequence> geneSequences,boolean showExonUppercase) throws Exception {
        FileOutputStream outputStream = new FileOutputStream(file);
        BufferedOutputStream bo = new BufferedOutputStream(outputStream);
        writeGeneSequence(bo, geneSequences,showExonUppercase);
        bo.close();
        outputStream.close();
    }

    /**
     * Write a collection of GeneSequences to a file where if the gene is negative strand it will flip and complement the sequence
     * @param outputStream
     * @param dnaSequences
     * @throws Exception
     */

    public static void writeGeneSequence(OutputStream outputStream, Collection<GeneSequence> geneSequences,boolean showExonUppercase) throws Exception {
        FastaGeneWriter fastaWriter = new FastaGeneWriter(
                outputStream, geneSequences,
                new GenericFastaHeaderFormat<GeneSequence, NucleotideCompound>(),showExonUppercase);
        fastaWriter.process();

    }


    /**
     * Write a collection of NucleotideSequences to a file
     * @param file
     * @param dnaSequences
     * @throws Exception
     */

    public static void writeNucleotideSequence(File file, Collection<DNASequence> dnaSequences) throws Exception {
        FileOutputStream outputStream = new FileOutputStream(file);
        BufferedOutputStream bo = new BufferedOutputStream(outputStream);
        writeNucleotideSequence(bo, dnaSequences);
        bo.close();
        outputStream.close();
    }

    /**
     * Write a collection of NucleotideSequences to a file
     * @param outputStream
     * @param dnaSequences
     * @throws Exception
     */

    public static void writeNucleotideSequence(OutputStream outputStream, Collection<DNASequence> dnaSequences) throws Exception {
        FastaWriter<DNASequence, NucleotideCompound> fastaWriter = new FastaWriter<DNASequence, NucleotideCompound>(
                outputStream, dnaSequences,
                new GenericFastaHeaderFormat<DNASequence, NucleotideCompound>());
        fastaWriter.process();

    }

    /**
     * Write a sequence to a file
     * @param file
     * @param sequence
     * @throws Exception
     */
    public static void writeSequence(File file, Sequence<?> sequence) throws Exception {
        FileOutputStream outputStream = new FileOutputStream(file);
        BufferedOutputStream bo = new BufferedOutputStream(outputStream);
        writeSequences(bo, singleSeqToCollection(sequence));
        bo.close();
        outputStream.close();
    }

    /**
     * Write a sequence to OutputStream
     * @param outputStream
     * @param sequence
     * @throws Exception
     */
    public static void writeSequence(OutputStream outputStream, Sequence<?> sequence) throws Exception {
        writeSequences(outputStream, singleSeqToCollection(sequence));
    }

    /**
     * 
     * @param sequence
     * @return
     */

    private static Collection<Sequence<?>> singleSeqToCollection(Sequence<?> sequence) {
        Collection<Sequence<?>> sequences = new ArrayList<Sequence<?>>();
        sequences.add(sequence);
        return sequences;
    }

    /**
     * Method which will write your given Sequences to the specified
     * {@link OutputStream}. This is a very generic method which writes just the
     * AccessionID of the Sequence as the FASTA header.
     *
     * @param outputStream Stream to write to; can be System.out
     * @param sequences The sequences to write out
     * @throws Exception Thrown normally thanks to IO problems
     */
    public static void writeSequences(OutputStream outputStream,
            Collection<Sequence<?>> sequences) throws Exception {

        FastaHeaderFormatInterface<Sequence<?>, Compound> fhfi =
                new FastaHeaderFormatInterface<Sequence<?>, Compound>() {

                    @Override
					public String getHeader(Sequence<?> sequence) {
                        return sequence.getAccession().toString();
                    }

                    ;
                };

        FastaWriter<Sequence<?>, Compound> fastaWriter =
                new FastaWriter<Sequence<?>, Compound>(outputStream,
                sequences, fhfi);

        fastaWriter.process();
    }
}
