#include "IncomingAggreGateCommand.h"
#include "util/SyntaxErrorException.h"
#include "util/simpleobject/AgString.h"
#include "util/StringUtils.h"
#include "IllegalArgumentException.h"
#include "IllegalStateException.h"
#include "UnsupportedOperationException.h"

static const char CLIENT_COMMAND_SEPARATOR = 0x17;

void IncomingAggreGateCommand::parse()
{
    if (getContent().length() == 0) {
        throw SyntaxErrorException("Zero length command received");
    }

    parameters = StringUtils::split(getContent(), CLIENT_COMMAND_SEPARATOR);
}

IncomingAggreGateCommand::IncomingAggreGateCommand(const unsigned char *data, int len)
    : AggreGateCommand()
{
    write(data, 0, len);
    parse();
}

IncomingAggreGateCommand::IncomingAggreGateCommand(const AgString &str)
    : AggreGateCommand()
{
    std::vector<unsigned char> data = str.getBytes(ASCII_CHARSET);
    if (data.size() > 0)
    {
        write(&data[0], 0, data.size());
    }
    parse();
}

IncomingAggreGateCommand::IncomingAggreGateCommand(const std::vector<unsigned char>& data)
    : AggreGateCommand()
{
    if (data.size() > 0)
    {
        write(&data[0], 0, data.size());
    }
    parse();
 }

int IncomingAggreGateCommand::getNumberOfParameters()
{
    return  parameters.size();
}

bool IncomingAggreGateCommand::hasParameter(int number)
{
    return number < getNumberOfParameters();
}

AgString &IncomingAggreGateCommand::getParameter(int number)
{
    if (number > getNumberOfParameters())
    {
        throw IllegalArgumentException("Trying to access parameter #" + AgString::fromInt(number) + " of command that has only " + AgString::fromInt(getNumberOfParameters()) + " parameters");
    }
    else
    {
        return parameters[number];
    }
}

std::vector<AgString> &IncomingAggreGateCommand::getParameters(int number)
{
    if (number != getNumberOfParameters())
    {
        throw IllegalArgumentException("Error getting command parameters: command has " + AgString::fromInt(getNumberOfParameters()) + " parameters, should have " + AgString::fromInt(number));
    }

    return parameters;
}

bool IncomingAggreGateCommand::isReply()
{
    if (getParameter(0).length() > 1)
    {
        throw IllegalStateException("Invalid command type: " + getParameter(0));
    }
    return (getParameter(0)[0] == AggreGateCommand::COMMAND_CODE_REPLY);
}

bool IncomingAggreGateCommand::isMessage()
{
    if (getParameter(0).length() > 1)
    {
        throw IllegalStateException("Invalid command type: " + getParameter(0));
    }

    return (getParameter(0)[0] == AggreGateCommand::COMMAND_CODE_MESSAGE);
}

AgString IncomingAggreGateCommand::getReplyCode()
{
    if (!isReply())
    {
        throw UnsupportedOperationException("Command is not a reply");
    }

    return getParameter(AggreGateCommand::INDEX_REPLY_CODE);
}

AgString IncomingAggreGateCommand::getMessageCode()
{
    if (!isMessage())
    {
        throw UnsupportedOperationException("Command is not a message");
    }

    return getParameter(AggreGateCommand::INDEX_MESSAGE_CODE);
}

AgString IncomingAggreGateCommand::getEncodedDataTable(int index)
{
    return getParameter(index);
}

AgString IncomingAggreGateCommand::getEncodedDataTableFromReply()
{
    if (!isReply())
    {
        throw UnsupportedOperationException("Command is not reply");
    }

    return getEncodedDataTable(AggreGateCommand::INDEX_DATA_TABLE_IN_REPLY);
}

AgString IncomingAggreGateCommand::getEncodedDataTableFromOperationMessage()
{
    if (!isMessage())
    {
        throw UnsupportedOperationException("Command is not message");
    }

    return getEncodedDataTable(AggreGateCommand::INDEX_OPERATION_MESSAGE_DATA_TABLE);
}

AgString IncomingAggreGateCommand::getEncodedDataTableFromEventMessage()
{
    if (!isMessage())
    {
        throw UnsupportedOperationException("Command is not message");
    }

    return getEncodedDataTable(AggreGateCommand::INDEX_EVENT_DATA_TABLE);
}

AgString IncomingAggreGateCommand::getId()
{
    return getNumberOfParameters() > AggreGateCommand::INDEX_ID ? getParameter(AggreGateCommand::INDEX_ID) : EMPTY_ID();
}

bool IncomingAggreGateCommand::isAsync()
{
    return isMessage();
}
