#include "datatable/DataTableBuilding.h"
#include "datatable/TableFormat.h"
#include "datatable/DataTable.h"
#include "datatable/FieldFormat.h"
#include "datatable/DataRecord.h"
#include "Cres.h"
#include "util/simpleobject/AgString.h"
#include "util/simpleobject/AgBoolean.h"
#include "AggreGateException.h"

DataTableBuilding::DataTableBuilding()
{
}

DataTablePtr DataTableBuilding::formatToFieldsTable(TableFormatPtr tf, bool readOnly)
{
    return formatToFieldsTable(tf, readOnly, ClassicEncodingSettingsPtr());
}

DataTablePtr DataTableBuilding::formatToFieldsTable(TableFormatPtr tf, bool readOnly, ClassicEncodingSettingsPtr settings)
{
    return formatToFieldsTable(tf, readOnly, settings, true);
}

DataTablePtr DataTableBuilding::formatToFieldsTable(TableFormatPtr tf, bool readOnly, ClassicEncodingSettingsPtr settings, bool ignoreHiddenFields)
{
    DataTablePtr res = DataTablePtr(new DataTable(FIELDS_FORMAT));

    for (std::vector<FieldFormat*>::iterator ff = tf->getFields().begin(); ff != tf->getFields().end(); ++ff)
    {
        if (ignoreHiddenFields && (*ff)->isHidden())
        {
            continue;
        }

        DataTablePtr selVals = DataTablePtr(new DataTable(SELECTION_VALUES_FORMAT));

        if ((*ff)->getSelectionValues().size() != 0)
        {
            std::vector< std::pair<AgObjectPtr,AgString> > &sels = (*ff)->getSelectionValues();

            for (std::vector< std::pair<AgObjectPtr,AgString> >::iterator it = sels.begin(); it != sels.end(); ++it)
            {
                selVals->addRecord(2, (*ff)->valueToString(it->first, settings).toUtf8().c_str(), it->second.toUtf8().c_str()); // fix gcc error: cannot pass objects of non-trivially-copyable type 'AgObjectPtr {aka class boost::shared_ptr<AgObject>}' through '...'
            }
        }


        DataRecordPtr rec = res->addRecord();

        rec->setValue(FIELD_FIELDS_FORMAT_OLDNAME(), (*ff)->getName().toObjectPtr());
        rec->setValue(FIELD_FIELDS_FORMAT_NAME(), (*ff)->getName().toObjectPtr());
        rec->setValue(FIELD_FIELDS_FORMAT_TYPE(), AgString((*ff)->getType()).toObjectPtr());
        rec->setValue(FIELD_FIELDS_FORMAT_DESCRIPTION(), (*ff)->getDescription().toObjectPtr());
        rec->setValue(FIELD_FIELDS_FORMAT_DEFAULT_VALUE(), (*ff)->valueToString((*ff)->getDefaultValue(), settings).toObjectPtr());
        rec->setValue(FIELD_FIELDS_FORMAT_READONLY(), AgObjectPtr(new AgBoolean(readOnly || (*ff)->isReadonly())));
        rec->setValue(FIELD_FIELDS_FORMAT_NULLABLE(), AgObjectPtr(new AgBoolean((*ff)->isNullable())));
        rec->setValue(FIELD_FIELDS_FORMAT_KEY(), AgObjectPtr(new AgBoolean((*ff)->isKeyField())));
        rec->setValue(FIELD_FIELDS_FORMAT_SELVALS(), selVals);
        rec->setValue(FIELD_FIELDS_FORMAT_EXTSELVALS(), AgObjectPtr(new AgBoolean((*ff)->isExtendableSelectionValues())));
        rec->setValue(FIELD_FIELDS_FORMAT_HIDDEN(), AgObjectPtr(new AgBoolean((*ff)->isHidden())));
        rec->setValue(FIELD_FIELDS_FORMAT_INLINE(), AgObjectPtr(new AgBoolean((*ff)->isInlineData())));
        rec->setValue(FIELD_FIELDS_FORMAT_HELP(), (*ff)->getHelp().toObjectPtr());

        try
        {
            rec->setValue(FIELD_FIELDS_FORMAT_EDITOR(), (*ff)->getEditor().toObjectPtr());
            rec->setValue(FIELD_FIELDS_FORMAT_EDITOR_OPTIONS(), (*ff)->getEditorOptions().toObjectPtr());
        }
        catch (AggreGateException &ex)
        {
            UNUSED(ex);
            // Not every editor is suitable here. Make sure all editors are listed in EDITOR_SELECTION_VALUES.
        }
    }

    return res;
}
