// ***************************************************************************
// BgzfStream_p.h (c) 2011 Derek Barnett
// Marth Lab, Department of Biology, Boston College
// ---------------------------------------------------------------------------
// Last modified: 17 January 2012(DB)
// ---------------------------------------------------------------------------
// Based on BGZF routines developed at the Broad Institute.
// Provides the basic functionality for reading & writing BGZF files
// Replaces the old BGZF.* files to avoid clashing with other toolkits
// ***************************************************************************

#ifndef BGZFSTREAM_P_H
#define BGZFSTREAM_P_H

#include "api/api_global.h"

//  -------------
//  W A R N I N G
//  -------------
//
// This file is not part of the BamTools API.  It exists purely as an
// implementation detail. This header file may change from version to version
// without notice, or even be removed.
//
// We mean it.

#include <cstddef>
#include <string>
#include "api/BamAux.h"
#include "api/IBamIODevice.h"

namespace BamTools {
namespace Internal {

class API_NO_EXPORT BgzfStream
{

    // constructor & destructor
public:
    BgzfStream();
    ~BgzfStream();

    // main interface methods
public:
    // closes BGZF file
    void Close();
    // returns true if BgzfStream open for IO
    bool IsOpen() const;
    // opens the BGZF file
    void Open(const std::string& filename, const IBamIODevice::OpenMode mode);
    // reads BGZF data into a byte buffer
    std::size_t Read(char* data, const std::size_t dataLength);
    // seek to position in BGZF file
    void Seek(const int64_t& position);
    // sets IO device (closes previous, if any, but does not attempt to open)
    void SetIODevice(IBamIODevice* device);
    // enable/disable compressed output
    void SetWriteCompressed(bool ok);
    // get file position in BGZF file
    int64_t Tell() const;
    // writes the supplied data into the BGZF buffer
    std::size_t Write(const char* data, const std::size_t dataLength);

    // internal methods
private:
    // compresses the current block
    std::size_t DeflateBlock(int32_t blockLength);
    // flushes the data in the BGZF block
    void FlushBlock();
    // de-compresses the current block
    std::size_t InflateBlock(const std::size_t& blockLength);
    // reads a BGZF block
    void ReadBlock();

    // static 'utility' methods
public:
    // checks BGZF block header
    static bool CheckBlockHeader(char* header);

    // data members
public:
    int32_t m_blockLength;
    int32_t m_blockOffset;
    int64_t m_blockAddress;

    bool m_isWriteCompressed;
    IBamIODevice* m_device;

    RaiiBuffer m_uncompressedBlock;
    RaiiBuffer m_compressedBlock;
};

}  // namespace Internal
}  // namespace BamTools

#endif  // BGZFSTREAM_P_H
