#ifndef INCLUDED_BOBCAT_CSVTABINS_
#define INCLUDED_BOBCAT_CSVTABINS_

#include <iosfwd>
#include <sstream>
#include <vector>
#include <string>
#include <iomanip>

#include <bobcat/string>

#include <bobcat/fmt>
#include <bobcat/sep>

namespace FBB
{
    // CSVTabIns objects are returned by members of CSVTable, and
    // allow for insertions into a line of the table. When the insertions
    // end CSVTabIns's destructor is called, ending the line. Its operator()
    // member is called by CSVTable's operator().

class CSVTabIns
{
    friend class CSVTable;

            // insert values of insertable types
    template <typename Type>
    friend CSVTabIns &operator<<(CSVTabIns &tab, Type const &value);    // 1.f

            // insert FMTs specifying LEFT, RIGHT, or CENTER
    friend CSVTabIns &operator<<(CSVTabIns &tab, FMT const &fmt);       // 2.f

            // insert FBB::left, FMT::right, FMT::center in the next col
    friend CSVTabIns &operator<<(CSVTabIns &tab, FMT::Align align);     // 3.f

            // writes a hline in the next column (calls hline())
    friend CSVTabIns &operator<<(CSVTabIns &tab, FMT::FMTHline);        // 4.f

            // change the separator while inserting (calls sep())
    friend CSVTabIns &operator<<(CSVTabIns &tab, Sep const &sep);       // 5.f

            // insert manipulators like std::left and std::right
    friend CSVTabIns &operator<<(CSVTabIns &tab,                        // 6.f
                                std::ios_base &(*func)(std::ios_base &));

    unsigned *d_tabIdx;
    unsigned d_idx;
    std::ostream *d_out;
    std::vector<FMT> const &d_format;
    std::string d_sep;

    FMT  d_extraFMT;
    bool d_useExtraFMT;                 // use d_extraFMT instead of d_format
    bool d_more;

    public:
        CSVTabIns(CSVTabIns const &other) = delete;
        ~CSVTabIns();

    private:
        CSVTabIns(unsigned *idx, std::ostream &out, 
                  std::vector<FMT> const &format, 
                  unsigned startIdx, std::string const &sep, bool more);
       
                                                    // inserts 1 row, via 
        void operator()(std::string const &text);   // CSVTable.operator()
        
        template <typename Type>
        std::string centered(FMT const &fmt,                        //     .f
                             unsigned fieldWidth, Type const &value);
        
                                            // total width incluing seps
                                            // (not using end's sep) from cols
        unsigned width(unsigned begin, unsigned end) const;     //      1.cc
        unsigned width(FMT const &fmt) const;       // see README       2.cc
        
        template <typename Type>                  // also updates d_idx
        void insertFormatted(FMT const &fmt,        //                     .f
                             Type const &value);    
        
        template <typename Type>
        CSVTabIns &insert(Type const &value);       //                    1.f
        
        CSVTabIns &sep(Sep const &sep);             //                     .f
        
        CSVTabIns &hline(FMT const &fmt);   // insert hline over fmt.nCols()
        
            // inserting FMT in col. d_idx means: if nCols() == 1: use the
            // FMT's width as precision, then use d_format[d_idx]'s width, and
            // set that format at d_extraFMT if nCols > 1: use the combined
            // width of the next nCols columns as width.
        
        CSVTabIns &insert(FMT const &fmt);          //                    2.cc
        CSVTabIns &insert(FMT::Align align);        //                    3.cc
        CSVTabIns &insert(std::ios_base &(*func)(std::ios_base &)); //    6.cc
};

#include "sep.f"
#include "insert1.f"
#include "centered.f"
#include "insertformatted.f"

#include "opinsert1.f"
#include "opinsert2.f"
#include "opinsert3.f"
#include "opinsert4.f"
#include "opinsert5.f"
#include "opinsert6.f"


} // FBB        
#endif



