#include "Table_impl.h"

#ifdef MM_WIN32
#pragma warning (disable : 4786)
#endif

#include "Line_impl.h"
#include "Create.h"
#include "Text.h"

#include <string>

using namespace std;

namespace MM
{

Table_impl::
Table_impl (Line * prototype)
:
    record_prototype_(prototype)
{
}

Table_impl::
~Table_impl()   
{
    //delete record_prototype_; //fix to ref
}

Line * Table_impl::
create_line () const
{
    return record_prototype_().clone ();
}

void Table_impl::
clear ()
{
    row_.clear();
    row_label_.clear();
    column_label_.clear();
}

void Table_impl::
get_text (int row, int column, Text & text)
{
    REQUIRE ("In range", row<height() && column<width());

    Any value = cell (row, column);
    const std::type_info &  type  = value.type();

    if      (type == typeid (Text))   text = any_cast <Text>   (value);
    else if (type == typeid (char *)) text = any_cast <char *> (value);
    else if (type == typeid (string)) text = any_cast <string> (value).c_str();
    else if (type == typeid (int))    text = any_cast <int>    (value);
    else if (type == typeid (double)) text = any_cast <double> (value);
    else if (type == typeid (long))   text = any_cast <long>   (value);
    else if (type == typeid (float))  text = any_cast <float>  (value);
    else                              text = "-";
}

bool Table_impl::
has_row_labels ()
{
    return row_label_.size() != 0;
}

bool Table_impl::
has_column_labels ()
{
    return column_label_.size() != 0;
}

const Text & Table_impl::
row_label (int row) const
{
    REQUIRE ("", row<height());
    return row_label_[row];
}

const Text & Table_impl::
column_label (int column) const
{
    REQUIRE ("", column<width());
    return column_label_[column];
}

void Table_impl::
set_row_label (int row, const Text & label)
{
    REQUIRE ("", row<height());
    row_label_[row] = label;
}

void Table_impl::
set_column_label (int column, const Text & label)
{
    REQUIRE ("", column<width());
    column_label_[column] = label;
}

Table * Table_impl::
clone() const              //fix
{
    Table_impl * twin =  new Table_impl (create_line ());
    return twin;
}

void Table_impl::
new_column (const Text & name)
{
    column_label_.push_back (name);
}

void Table_impl::
adopt (Line * record)
{
    REQUIRE ("Record in range", record->length() <= width());
    row_.push_back (record);
    row_label_.push_back (Text() + "#" + row_label_.size());   //fix remove
}

}//MM
