#ifndef INCLUDED_BOBCAT_MULTISTREAMBUF_
#define INCLUDED_BOBCAT_MULTISTREAMBUF_

#include <cstdio>
#include <streambuf>
#include <vector>
#include <ostream>
#include <string>

namespace FBB
{

class MultiStreambuf: public std::streambuf
{
    public:
        enum Mode
        {
            OFF,                // stream not used
            ON,                 // stream always used
            ONCE,               // stream used until flushed
            RESET,              // stream once used. Set to ONCE to re-use
        };

        class stream            // holds a pointer to a stream and a indicator
        {                       // telling us whether or not to use the stream
            friend class MultiStreambuf;

            std::ostream *d_os;
            Mode          d_mode;

            public:
                stream(std::ostream &os, Mode mode = ON);   // 1.f
                void setMode(Mode mode);                    // .f
                Mode mode() const;                          // .f
                std::ostream &ostream();                    // .f
            private:
                static void setOnce(stream &os);            // .f
        };

        typedef std::vector<stream>::iterator iterator;
        typedef std::vector<stream>::const_iterator const_iterator;

    private:
        std::string d_buffer;
        std::vector<stream> d_os;

    public:
        MultiStreambuf()    = default;
        explicit MultiStreambuf(std::ostream &os, Mode mode = ON);      // 1.f
        explicit MultiStreambuf(std::vector<stream> const &osvector);   // 2.f

        void insert(std::ostream &os, Mode mode = ON);                  // 1.f
        void insert(std::vector<stream> const &os);                     // 2.f
        iterator begin();                                               // 1.f
        iterator end();                                                 // 1.f
        const_iterator begin() const;                                   // 2.f
        const_iterator end() const;                                     // 2.f
        void setOnce();             // reset all `RESET' modes to `ONCE'
        
    protected:
        int pSync();

    private:
        virtual int overflow(int c);
        virtual std::streamsize xsputn(char const *buffer, std::streamsize n);
        virtual int sync();

        struct Insert;

        static void insertStruct(stream &os, Insert &insert); 
};

#include "mode.f"
#include "ostream.f"
#include "setmode.f"
#include "setonce.f"
#include "stream1.f"

#include "multistreambuf1.f"
#include "multistreambuf2.f"

#include "begin1.f"
#include "begin2.f"
#include "end1.f"
#include "end2.f"
#include "insert1.f"
#include "insert2.f"

} // namespace FBB
        
#endif
