#include "expression/Evaluator.h"
#include "expression/DefaultReferenceResolver.h"
#include "expression/ReferenceResolver.h"
#include "expression/EnvironmentReferenceResolver.h"
#include "expression/Function.h"
#include "util/Util.h"

Evaluator::Evaluator(ContextManager* cm, CallerControllerPtr caller)
{
    ctor(cm, NULL, DataTablePtr(), caller);
}

Evaluator::Evaluator(DataTablePtr defaultTable)
{
    ctor(NULL ,NULL, defaultTable, CallerControllerPtr());
}

Evaluator::Evaluator(ContextManager* cm, Context* defaultContext, DataTablePtr defaultTable, CallerControllerPtr caller)
{
    ctor(cm, defaultContext, defaultTable, caller);
}

Evaluator::Evaluator(ReferenceResolverPtr resolver)
{
    init_(resolver);
}

void Evaluator::ctor(ContextManager* cm, Context* defaultContext, DataTablePtr defaultTable, CallerControllerPtr caller)
{
    UNUSED(cm);
    UNUSED(defaultContext);
    UNUSED(defaultTable);
    UNUSED(caller);
}

void Evaluator::init_(ReferenceResolverPtr defaultResolver)
{
    //TODO: this
    //defaultResolver->setEvaluator(this);
    resolvers.insert(std::pair<AgString, ReferenceResolverPtr>("", defaultResolver));
    setResolver(Reference::SCHEMA_ENVIRONMENT(), environmentResolver);
}

AgObjectPtr Evaluator::evaluate(ExpressionPtr expression)
{
    return evaluate(expression, EvaluationEnvironmentPtr(new EvaluationEnvironment()));
}

AgObjectPtr Evaluator::evaluate(ExpressionPtr expression, EvaluationEnvironmentPtr environment)
{
    UNUSED(expression);
    UNUSED(environment);
    //TODO
    return AgObjectPtr();
}

AgString Evaluator::evaluateToString(boost::shared_ptr<Expression> expression)
{
    UNUSED(expression);
    return "";
}

AgString Evaluator::evaluateToStringOrNull(boost::shared_ptr<Expression> expression)
{
    UNUSED(expression);
    return "";
}


bool Evaluator::evaluateToBoolean(ExpressionPtr expression)
{
    UNUSED(expression);
    return false;
}


ReferenceResolverPtr Evaluator::getDefaultResolver()
{
    return resolvers[""];
}

void Evaluator::setResolver(const AgString & schema, ReferenceResolverPtr resolver)
{
    resolvers.insert(std::pair<AgString, ReferenceResolverPtr>(schema, resolver) );
}
