#ifndef HTIO2_SEQ_IO_H
#define	HTIO2_SEQ_IO_H

#include <zlib.h>

#include "htio2/Enum.h"
#include "htio2/RefCounted.h"


namespace htio2
{

class SimpleSeq;
class FastqSeq;
class FileHandle;


class SeqIO : public RefCounted
{
public:
    typedef SmartPtr<SeqIO> Ptr;
    typedef SmartPtr<const SeqIO> ConstPtr;

public:
    /**
     * create sequence IO object by file name
     * @param file file to open
     * @param mode read/write/append
     * @param comp compress format. COMPRESS_UNKNOWN for automatically guess.
     */
    SeqIO(const std::string& file, IOMode mode, CompressFormat comp = COMPRESS_UNKNOWN);

    /**
     * create sequence IO object from HTIO file handle object
     * @param handle
     */
    SeqIO(FileHandle* handle);

    /**
     * create sequence IO object from C standard file handle
     * @param handle
     * @param auto_close if set to true, the underlying handle will be closed when sequence IO object is destroyed
     */
    SeqIO(FILE* handle, bool auto_close = true);

    /**
     * create sequence IO object from Zlib file handle
     * @param handle
     * @param auto_close if set to true, the underlying handle will be closed when sequence IO object is destroyed
     */
    SeqIO(gzFile handle, bool auto_close = true);

    /**
     * Create a sequence IO object. The sequence format is automatically guessed by file name and/or content.
     * @param file filename
     * @param mode READ/WRITE/APPEND
     * @param comp compress format. COMPRESS_UNKNOWN for automatically guess.
     * @return the newly created sequence IO object
     */
    static SeqIO* New(const std::string& file, IOMode mode, CompressFormat comp = COMPRESS_UNKNOWN);

    /**
     * Create a sequence IO object from HTIO FileHandle object. The sequence format is automatically guessed by file content.
     * @param handle HTIO FileHandle object. Must be readable.
     * @return the newly created sequence IO object
     */
    static SeqIO* New(FileHandle* handle);

    /**
     * Create a sequence IO object from C standard file handle. The sequence format is automatically guessed by file content.
     * @param handle C standard file handle. Must be readable.
     * @param auto_close If set to true, the underlying handle will be closed when the sequence IO object is destroyed.
     * @return 
     */
    static SeqIO* New(FILE* handle, bool auto_close = true);

    /**
     * Create a sequence IO object from Zlib file handle. The sequence format is automatically guessed by file content.
     * @param handle Zlib file handle
     * @param auto_close If set to true, the underlying handle will be closed when the sequence IO object is destroyed.
     * @return 
     */
    static SeqIO* New(gzFile handle, bool auto_close = true);

    virtual ~SeqIO();

    /**
     * Seek to a file offset.
     * @param offset
     * @param whence 0 for absolute, 1 for relative
     */
    virtual void seek(off_t offset, int whence = SEEK_SET);

    /**
     * get the current file offset
     * @return file offset.
     */
    virtual off_t tell() const;


    /**
     * read one sequence
     * @param result
     * @return true if got a seq, false if reached end of file
     */
    virtual bool next_seq(SimpleSeq& output) = 0;

    /**
     * read one sequence with quality
     * @param result
     * @return true if got a seq, false if reached end of file
     */
    virtual bool next_seq(FastqSeq& output) = 0;

    /**
     * write one sequence
     * @param seq the sequence to be written
     */
    virtual void write_seq(const SimpleSeq& seq) = 0;

    /**
     * write one sequence
     * @param seq the sequence to be written
     */
    virtual void write_seq(const FastqSeq& seq) = 0;

protected:
    FileHandle* handle;
    std::string buffer;

private:
    SeqIO(const SeqIO& other);
    SeqIO& operator =(const SeqIO& other);
};

} // namespace htio2

#endif	/* HTIO2_SEQ_IO_H */

