#include "binding/EvaluationOptions.h"
#include "expression/Reference.h"
#include "expression/Expression.h"

EvaluationOptions::EvaluationOptions()
{
    period = 0;
}

EvaluationOptions::EvaluationOptions(int pattern)
{
    period = 0;
    this->pattern = pattern;
}

EvaluationOptions::EvaluationOptions(bool startup, bool event)
{
	init(startup, event, 0);
}

void EvaluationOptions::init(bool startup, bool event, int64_t period)
{
	this->period = 0;
    this->pattern = 0;

    if (startup)
    {
        pattern |= STARTUP;
    }
    if (event)
    {
        pattern |= EVENT;
    }
    if (period > 0)
    {
        pattern |= PERIODIC;
        this->period = period;
    }
}

EvaluationOptions::EvaluationOptions(bool startup, bool event, int64_t period)
{
    init(startup, event, period);
}

EvaluationOptions::EvaluationOptions(bool startup, const AgString & activator, const AgString & condition)
{
    init(startup, activator);
    this->condition = ExpressionPtr(new Expression(condition));
}

void EvaluationOptions::init(bool startup, const AgString & activator)
{
	this->period = 0;
    this->pattern = 0;
    if (startup)
    {
        pattern |= STARTUP;
    }
    pattern |= EVENT;
    setActivator(ReferencePtr(new Reference(activator)));
}

EvaluationOptions::EvaluationOptions(bool startup, const AgString & activator)
{
    init(startup, activator);
}

int EvaluationOptions::getPattern()
{
    return pattern;
}

int64_t EvaluationOptions::getPeriod()
{
    return period;
}

ReferencePtr EvaluationOptions::getActivator()
{
    return activator;
}

ExpressionPtr EvaluationOptions::getCondition()
{
    return condition;
}

void EvaluationOptions::setPattern(int pattern)
{
    this->pattern = pattern;
}

void EvaluationOptions::setPeriod(int64_t period)
{
    this->period = period;
}

void EvaluationOptions::setActivator(ReferencePtr activator)
{
    this->activator = activator;
}

void EvaluationOptions::setCondition(ExpressionPtr condition)
{
    this->condition = condition;
}

bool EvaluationOptions::isProcessOnStartup()
{
    return (pattern & STARTUP) > 0;
}

bool EvaluationOptions::isProcessOnEvent()
{
    return (pattern & EVENT) > 0;
}

bool EvaluationOptions::isProcessPeriodically()
{
    return (pattern & PERIODIC) > 0;
}

void EvaluationOptions::setProcessOnStartup(bool /*processOnStartup*/)
{
    this->pattern |= STARTUP;
}

void EvaluationOptions::setProcessOnEvent(bool /*processOnEvent*/)
{
    this->pattern |= EVENT;
}

void EvaluationOptions::setProcessPeriodically(bool /*processPeriodically*/)
{
    this->pattern |= PERIODIC;
}

Cloneable* EvaluationOptions::clone()
{
    EvaluationOptions *eo = new EvaluationOptions();
    eo->pattern = this->pattern;
    eo->period = this->period;

    if (activator.get())
    {
        eo->activator = ReferencePtr(activator->clone());
    }
    if (condition.get())
    {
        eo->condition = ExpressionPtr(condition->clone());
    }

    return eo;
}

AgString EvaluationOptions::toString()
{
    return (isProcessOnStartup() ? AgString("1") : AgString("0")) + (isProcessOnEvent() ? AgString("1") : AgString("0")) +
            (isProcessPeriodically() ? AgString("1") : AgString("0")) + (isProcessPeriodically() ? ", period=" + AgString::fromInt64(period) : "") + ", activator="
            + activator->toString() + ", condition=" + condition->toString();
}
