#ifndef INCLUDED_BOBCAT_OFOLDSTREAM_
#define INCLUDED_BOBCAT_OFOLDSTREAM_

#include <iosfwd>
#include <ostream>
#include <fstream>

#include <bobcat/ofoldbuf>

namespace FBB
{

    // 'virtual public OFoldBufBlanks is used to avoid 'base class not
    // accessible' warnings since OFoldBuf also inherits from
    // OFoldBufBlanks and only one struct definition is needed in the
    // final OFoldStream class.
class OFoldStream: virtual public OFoldBufEnums,
                   private OFoldBuf, public std::ostream
{
    public:
        OFoldStream()           = default;

        explicit OFoldStream(std::string const &fname,              // 1.f
                    size_t leftIndent = 0, size_t rightMargin = 80,
                    TabsOrBlanks tob = BLANKS,
                    TrailingBlanks tb = IGNORE_TRAILING_BLANKS);

        explicit OFoldStream(std::ostream &dest,                    // 2.f
                    size_t leftIndent = 0, size_t rightMargin = 80,
                    TabsOrBlanks tob = BLANKS,
                    TrailingBlanks tb = IGNORE_TRAILING_BLANKS);

        void reset(std::string const &fname,
                  size_t leftIndent = 0, size_t rightMargin = 80,
                  TrailingBlanks tb = IGNORE_TRAILING_BLANKS);

        void reset(std::ostream &out,
                  size_t leftIndent = 0, size_t rightMargin = 80,
                  TrailingBlanks tb = IGNORE_TRAILING_BLANKS);

        void setMargins(size_t leftMargin, size_t rightMargin);     // .f
        void setTrailingBlanks(TrailingBlanks tb);                  // .f
        void useBlanks();                                           // .f
        void useTabs(size_t tabWidth = 8);                          // .f

        static size_t leftMargin(std::ostream const &os);           // .f
        static size_t rightMargin(std::ostream const &os);          // .f
};

inline OFoldStream::OFoldStream(std::string const &fname,
                    size_t leftIndent, size_t rightMargin,
                    TabsOrBlanks tob, TrailingBlanks tb)
:
    OFoldBuf(fname, leftIndent, rightMargin, tob, tb),
    std::ostream(this)
{}
inline OFoldStream::OFoldStream(std::ostream &out,
                    size_t leftIndent, size_t rightMargin,
                    TabsOrBlanks tob, TrailingBlanks tb)
:
    OFoldBuf(out, leftIndent, rightMargin, tob, tb),
    std::ostream(this)
{}

inline size_t OFoldStream::leftMargin(std::ostream const &os)
{
    return OFoldBuf::leftMargin(os.rdbuf());
}
inline size_t OFoldStream::rightMargin(std::ostream const &os)
{
    return OFoldBuf::rightMargin(os.rdbuf());
}
inline void OFoldStream::setMargins(size_t lm, size_t rm)
{
    OFoldBuf::setMargins(lm, rm);
}
inline void OFoldStream::setTrailingBlanks(TrailingBlanks tb)
{
    OFoldBuf::setTrailingBlanks(tb);
}
inline void OFoldStream::useBlanks()
{
    OFoldBuf::useBlanks();
}
inline void OFoldStream::useTabs(size_t tabWidth)
{
    OFoldBuf::useTabs(tabWidth);
}

} // FBB

#endif
