#include "binding/BindingEventsHelper.h"
#include "datatable/field/StringFieldFormat.h"
#include "datatable/TableFormat.h"
#include "datatable/DataTable.h"
#include "datatable/DataRecord.h"
#include "context/Context.h"
#include "binding/EvaluationOptions.h"
#include "binding/Binding.h"
#include "Cres.h"
#include "AggreGateException.h"
#include "GlobalVars.h"

TableFormatPtr BindingEventsHelper::EFT_BINDING_EXECUTION = BindingEventsHelper::EFT_BINDING_EXECUTION_();
TableFormatPtr BindingEventsHelper::EFT_BINDING_EXECUTION_EXT = BindingEventsHelper::EFT_BINDING_EXECUTION_EXT_();
TableFormatPtr BindingEventsHelper::EFT_BINDING_ERROR = BindingEventsHelper::EFT_BINDING_ERROR_();
TableFormatPtr BindingEventsHelper::EFT_BINDING_ERROR_EXT = BindingEventsHelper::EFT_BINDING_ERROR_EXT_();


TableFormatPtr BindingEventsHelper::EFT_BINDING_EXECUTION_()
{
    TableFormatPtr tf = TableFormatPtr(new TableFormat(1, 1));

    tf->addField(FieldFormat::create("<" + EF_BINDING_TARGET() + "><S><D=" + Cres::get()->getString("target")
                                                            + "><F=N><E=" + AGG_GLOBAL.EDITOR_CONTEXT + ">"));
    tf->addField(FieldFormat::create("<" + EF_BINDING_EXPRESSION() + "><S><F=N><D=" + Cres::get()->getString("expression") + ">"));
    tf->addField(FieldFormat::create("<" + EF_BINDING_VALUE() + "><S><F=N><D=" + Cres::get()->getString("value") + ">"));
    tf->addField(FieldFormat::create("<" + EF_BINDING_ACTIVATOR() + "><S><F=N><D=" + Cres::get()->getString("wActivatorDescr") + ">"));
    tf->addField(FieldFormat::create("<" + EF_BINDING_CONDITION() + "><S><F=N><D=" + Cres::get()->getString("condition") + ">"));
    tf->addField(FieldFormat::create("<" + EF_BINDING_EXECUTION() + "><S><D=" + Cres::get()->getString("wExecution") + ">"));
    tf->addField(FieldFormat::create("<" + EF_BINDING_CAUSE() + "><S><F=N><D=" + Cres::get()->getString("cause") + ">"));

    return tf;
}


TableFormatPtr BindingEventsHelper::EFT_BINDING_EXECUTION_EXT_()
{
    TableFormatPtr tf = EFT_BINDING_EXECUTION_();

    tf->addField(FieldFormat::create("<" + EF_BINDING_CONTEXT() + "><S><D="
                                    + Cres::get()->getString("context") + "><F=N><E=" + AGG_GLOBAL.EDITOR_CONTEXT + ">"));

    return tf;
}


TableFormatPtr BindingEventsHelper::EFT_BINDING_ERROR_()
{
    TableFormatPtr tf = EFT_BINDING_EXECUTION_();

    tf->removeField(EF_BINDING_VALUE());
    tf->removeField(EF_BINDING_CONDITION());
    tf->addField(FieldFormat::create("<" + EF_BINDING_ERROR() + "><S><D="
                                        + Cres::get()->getString("error") + "><E=" + AGG_GLOBAL.EDITOR_TEXT_AREA + ">"));
    tf->addField(FieldFormat::create("<" + EF_BINDING_ERROR_STACK() + "><T><D="
                                                + Cres::get()->getString("stack") + ">"));

    return tf;
}


TableFormatPtr BindingEventsHelper::EFT_BINDING_ERROR_EXT_()
{
    TableFormatPtr tf = EFT_BINDING_ERROR_();
    tf->addField(FieldFormat::create("<" + EF_BINDING_CONTEXT() + "><S><D="
                                                                + Cres::get()->getString("context") + "><F=N>"));
    return tf;
}

DataTablePtr BindingEventsHelper::createBindingErrorEventDataPtr(ContextPtr /*con*/, BindingPtr /*binding*/, int /*method*/,
                                                                 const AgString & /*activator*/, AggreGateExceptionPtr /*error*/)
{
    //not used
    assert(0);
    return DataTablePtr();
}

DataTablePtr BindingEventsHelper::createBindingExecutionEventDataPtr(ContextPtr /*con*/, int /*method*/,BindingPtr /*binding*/,
                                                                     EvaluationOptionsPtr /*options*/, ReferencePtr /*cause*/,
                                                                     AgObjectPtr /*result*/)
{
    //not used
    assert(0);
    return DataTablePtr();
}

AgString BindingEventsHelper::executionTypeDescription(int method)
{
    AgString exec;
    if (method == EvaluationOptions::STARTUP)
    {
        exec = Cres::get()->getString("wOnStartup");
    }
    else if (method == EvaluationOptions::EVENT)
    {
        exec = Cres::get()->getString("wOnEvent");
    }
    else
    {
        exec = Cres::get()->getString("wPeriodically");
    }

    return exec;
}
