#ifndef INCLUDED_BOBCAT_TABLEBUF_
#define INCLUDED_BOBCAT_TABLEBUF_

#include <streambuf>

#include <bobcat/tablebase>
#include <bobcat/exception>

namespace FBB
{

class TableBuf: public TableBase, public std::streambuf
{
    friend std::ostream &operator<<(std::ostream &str,              // 1.f
                                    TableBuf &table);

    friend std::ostream &fs(std::ostream &out);
    friend std::ostream &rs(std::ostream &out);

    int d_fs;
    int d_rs;
    std::string d_str;
    bool d_buffered;
    bool d_insertEmptyRow;

    public:
        TableBuf(size_t nColumns, FillDirection direction,          // 0
                                WidthType widthType = COLUMNWIDTH);

        TableBuf(TableSupport &tableSupport,                        // 1
                size_t nColumns, FillDirection direction,
                WidthType widthType = COLUMNWIDTH);

        TableBuf &def();                // fillup an incomplete table  1.f
        TableBuf &setAlign(Align const &align);    // set alignment    .f

        void setFieldSeparator();                                   // 1.f
        void setFieldSeparator(char fs);                            // 2.f
        void setRowSeparator();                                     // 1.f
        void setRowSeparator(char rs);                              // 2.f

    private:
        int sync() override;
        int overflow(int ch) override;

        void nextField();
        void endRow();

};

std::ostream &fs(std::ostream &out);
std::ostream &rs(std::ostream &out);

inline TableBuf &TableBuf::setAlign(Align const &align)
{
    TableBase::setAlign(align);
    return *this;
}
inline void TableBuf::setFieldSeparator()
{
    d_fs = -1;
}
inline void TableBuf::setFieldSeparator(char fs)
{
    d_fs = fs;
}
inline void TableBuf::setRowSeparator()
{
    d_rs = -1;
}
inline void TableBuf::setRowSeparator(char rs)
{
    d_rs = rs;
}

    // Free Members

inline TableBuf &def(TableBuf &table)
{
    return table.def();
}

                        // Insert column or element alignments
inline TableBuf &operator<<(TableBuf &tab, Align const &align)
{
    return tab.setAlign(align);
}

} // FBB

#endif
