#include "expression/ExpressionUtils.h"
#include "IllegalArgumentException.h"

#include <math.h>
#include <sstream>

std::vector<boost::shared_ptr<void> > ExpressionUtils::getFunctionParameters(AgString paramsString, bool allowExpressions)
{
    std::vector<boost::shared_ptr<void> > params;

    bool insideSingleQuotedLiteral = false;
    bool insideDoubleQuotedLiteral = false;
    bool escaped = false;
    AgString *buf = new AgString();

    for (int i = 0; i < paramsString.Length(); i++)
    {
        char c = paramsString.CharAt(i);
        if (c == PARAMS_ESCAPE)
        {
            if (escaped)
            {
                escaped = false;
                *buf += c;
                continue;
            }
            else
            {
                escaped = true;
                continue;
            }
        }
        else if (insideSingleQuotedLiteral)
        {
            if (c == PARAM_ESCAPE_SINGLE)
            {
                if (!escaped)
                {
                    insideSingleQuotedLiteral = false;
                    AgString param = *buf;
                    if (allowExpressions)
                    {
                        params.push_back(boost::shared_ptr<Expression> (new Expression(param)));
                    }
                    else
                    {
                        params.push_back(boost::shared_ptr<AgString> (new AgString(param)));
                    }
                    buf = NULL;
                }
            }
        }
        else if (insideDoubleQuotedLiteral)
        {
            if (c == PARAM_ESCAPE_DOUBLE)
            {
                if (!escaped)
                {
                    insideDoubleQuotedLiteral = false;
                    AgString param = *buf;
                    params.push_back(boost::shared_ptr<AgString> (new AgString(param)));
                    buf = NULL;
                }
            }
        }
        else if (c == PARAMS_DELIM)
        {
            if (!insideSingleQuotedLiteral && !insideDoubleQuotedLiteral)
            {
                if (buf != NULL)
                {
                    AgString param = buf->trim();
                    if (param.Length() > 0)
                    {
                        params.push_back(boost::shared_ptr<Expression> (new Expression(param)));
                    }
                }

                *buf = "";
                continue;
            }
        }
        else if (c == PARAM_ESCAPE_SINGLE && !insideDoubleQuotedLiteral)
        {
            insideSingleQuotedLiteral = true;
            *buf = "";
            continue;
        }
        else if (c == PARAM_ESCAPE_DOUBLE && !insideSingleQuotedLiteral)
        {
            insideDoubleQuotedLiteral = true;
            *buf = "";
            continue;
        }

        if (c != PARAMS_ESCAPE)
        {
            escaped = false;
        }
    }

    if (buf != NULL)
    {
        AgString param = buf->trim();
        if (param.Length() > 0)
        {
            params.push_back(boost::shared_ptr<Expression> (new Expression(param)));
        }
    }

    delete buf;

    if (insideSingleQuotedLiteral || insideDoubleQuotedLiteral)
    {
        throw IllegalArgumentException("Illegal function parameters!");
    }

    return params;
}
