#ifndef _INCLUDED_BOBCAT_TABLESPEC_
#define _INCLUDED_BOBCAT_TABLESPEC_

#include <string>
#include <vector>

#include <bobcat/tablesupport>

namespace FBB
{
    class TableSpec;
}

std::ostream &operator<<(std::ostream &str, FBB::TableSpec const &tableType);

namespace FBB
{

class TableSpec
{
    friend std::ostream &::operator<<(std::ostream &str, 
                                    FBB::TableSpec const &tableType); 
    public:
        enum WidthType
        {
            EqualWidth,
            ColumnWidth,
        };
        enum FillDirection
        {
            Horizontal,
            Vertical
        };

    private:
        TableSupport           *d_tableSupportPtr;
        TableSupport           &d_tableSupport;
        size_t                d_maxWidth;
        size_t                d_nRows;
        size_t                d_nColumns;
        WidthType               d_widthType;
        std::vector<size_t>   d_colWidth;
        size_t               (TableSpec::*d_widthFun)
                                        (size_t col) const;
        std::string const     &(TableSpec::*d_indexFun)
                                        (size_t row, size_t col) const;

    protected:
        std::vector<std::string> d_string;

    public:
        void setWidth(WidthType type);
        
    protected:
        TableSpec(TableSupport &tableSupport, size_t nColumns,
                    FillDirection direction);

        TableSpec(size_t nColumns, FillDirection direction);

        ~TableSpec()
        {
            delete d_tableSupportPtr;
        }
        void init();

    private:
        std::ostream &insert(std::ostream &ostr) const;
        size_t width(size_t col) const  // returns correct column width,
        {                                   // given d_widthType
            return (this->*d_widthFun)(col);
        }

        size_t maxWidth(size_t) const
        {
            return d_maxWidth;
        }
        size_t columnWidth(size_t col) const
        {
            return d_colWidth[col];
        }
                                    // returns string at particular location
        std::string const &stringAt(size_t row, size_t col) const
        {
            return (this->*d_indexFun)(row, col);
        }

        std::string const &hIndex(size_t row, size_t col) const
        {
            return d_string[row * d_nColumns + col];
        }
        std::string const &vIndex(size_t row, size_t col) const
        {
            return d_string[col * d_nRows + row];
        }


};

} // FBB

#endif
