#ifndef _INCLUDED_BOBCAT_TABLE_
#define _INCLUDED_BOBCAT_TABLE_

// #include <bobcat/tablespec>

namespace FBB
{

    // By making this an Iterator rather than a data-type any kind of iterator
    // may be used supporting the dereference and increment operators:
    // istream_iterators, const_iterators, pointers etc.
template <typename Iterator>
class Table: public TableSpec
{
    public:
        Table(Iterator const &begin, Iterator const &end, 
                TableSupport &tableSupport,
                size_t nColumns, FillDirection direction);
        Table(Iterator const &begin, Iterator const &end, 
                size_t nColumns, FillDirection direction);
        Table(TableSupport &tableSupport,
              size_t nColumns, FillDirection direction);
        Table(size_t nColumns, FillDirection direction);

        Table<Iterator> &append(string const &str, char const *sep = " \t",
                                bool addEmpty = false);
    private:
        void fill(Iterator begin, Iterator const &end);

        Table(Table<Iterator> const &other);                        // NI
        Table<Iterator> &operator=(Table<Iterator> const &other);   // NI
};

template <typename Iterator>
Table<Iterator> &Table<Iterator>::append(String const &str, char const *sep, 
                                         bool addEmpty)
{
    TableSpec::append(str, sep, addEmpty);
    return *this;
}

template <typename Iterator>
void Table<Iterator>::fill(Iterator it, Iterator const &end)
{
    while (it != end)
    {
        std::ostringstream str;
        str << *it++;
        push_back(str.str());
    }
    tabulate();
}

template <typename Iterator>
Table<Iterator>::Table(Iterator const &begin, Iterator const &end, 
                TableSupport &tableSupport,
                size_t nColumns, FillDirection direction)
:
    TableSpec(tableSupport, nColumns, direction)
{
    fill(begin, end);
}

template <typename Iterator>
Table<Iterator>::Table(Iterator const &begin, Iterator const &end, 
                size_t nColumns, FillDirection direction)
:
    TableSpec(nColumns, direction)
{
    fill(begin, end);
}

template <typename Iterator>
Table<Iterator>::Table(TableSupport &tableSupport,
                       size_t nColumns, FillDirection direction)
:
    TableSpec(tableSupport, nColumns, direction)
{}

template <typename Iterator>
Table<Iterator>::Table(size_t nColumns, FillDirection direction)
:
    TableSpec(nColumns, direction)
{}


template <typename Iterator>
void next(Table<Iterator> &obj)
{
    obj.next();
}

template <typename Iterator>
void tabulate(Table<Iterator> &obj)
{
    obj.tabulate();
}

} // FBB

namespace std
{

template <typename Iterator, typename Type>
FBB::Table<Iterator> &operator<<(FBB::Table<Iterator> &obj, Type const &x)
{
    reinterpret_cast<ostringstream &>(obj) << x;
    return obj;
}

template <typename Iterator>
FBB::Table<Iterator> &operator<<(FBB::Table<Iterator> &obj, 
                                 ostream &(*fp)(ostream &))
{
    reinterpret_cast<ostringstream &>(obj) << *fp;
    return obj;
}

template <typename Iterator>
FBB::Table<Iterator> &operator<<(FBB::Table<Iterator> &obj, 
         void (*fp)(FBB::Table<Iterator> &))
{
    (*fp)(obj);
    return obj;
}

} // std



#endif
