#include "communication/CommandProcessorStatistics.h"
#include "datatable/DataTableException.h"
#include "datatable/DataTableConversion.h"
#include "datatable/DataTable.h"
#include "datatable/TableFormat.h"
#include "datatable/field/LongFieldFormat.h"
#include "util/TimeHelper.h"
#include "IllegalStateException.h"
#include "Cres.h"
#include "GlobalVars.h"

TableFormatPtr CommandProcessorStatistics::FORMAT = CommandProcessorStatistics::initFORMAT();

TableFormatPtr CommandProcessorStatistics::initFORMAT()
{
    TableFormatPtr tf = TableFormatPtr(new TableFormat(1, 1));
    tf->addField("<connectionTime><L><F=N><D=" + Cres::get()->getString("commConnectionTime") + "><E=" + AGG_GLOBAL.EDITOR_PERIOD + "><O="
                + LongFieldFormat::encodePeriodEditorOptions(TimeHelper::SECOND(), TimeHelper::DAY()) + ">");
    tf->addField("<commandCount><L><D=" + Cres::get()->getString("commCommandCount") + ">");
    tf->addField("<averageResponseTime><L><D=" + Cres::get()->getString("commAvgResponseTime") + "><E=" + AGG_GLOBAL.EDITOR_PERIOD + "><O="
                + LongFieldFormat::encodePeriodEditorOptions(TimeHelper::MILLISECOND(), TimeHelper::MILLISECOND()) + ">");
    tf->addField("<incomingTraffic><L><D=" + Cres::get()->getString("commIncomingTraffic") + "><E=" + AGG_GLOBAL.EDITOR_BYTES + ">");
    tf->addField("<outgoingTraffic><L><D=" + Cres::get()->getString("commOutgoingTraffic") + "><E=" + AGG_GLOBAL.EDITOR_BYTES + ">");
    tf->addField("<unrepliedCommandCount><L><D=" + Cres::get()->getString("commUnrepliedCommandCount") + ">");

    return tf;
}

CommandProcessorStatistics::CommandProcessorStatistics()
{
    this->commandCount = 0;
    this->outgoingTraffic = 0;
    this->incomingTraffic = 0;
    this->unrepliedCommandCount = 0;
    this->averageResponseTime = 0;
}

void CommandProcessorStatistics::update(ReplyMonitorPtr monitor)
{
    if (commandCount == 0) {
        startTime = boost::posix_time::microsec_clock::local_time();
    }

    commandCount++;

    boost::posix_time::time_duration td = boost::posix_time::microsec_clock::local_time() - monitor->getStartTime();
    averageResponseTime = (float)(averageResponseTime * (float)(commandCount - 1) + td.total_milliseconds()) / (float)commandCount;

    outgoingTraffic += monitor->getCommand()->size();

    if (monitor->getReply() != NULL) {
        incomingTraffic += monitor->getReply()->size();
    }else {
        unrepliedCommandCount++;
    }
}

DataTablePtr CommandProcessorStatistics::toDataTable()
{
    assert(0);
    try {
        return DataTableConversion::instance().beanToTable(0/*this*/, FORMAT);
    }catch (DataTableException ex) {
        throw IllegalStateException(ex.getMessage(), ex.getDetails());
    }
}

boost::posix_time::ptime CommandProcessorStatistics::getStartTime()
{
    return startTime;
}

boost::posix_time::time_duration CommandProcessorStatistics::getConnectionTime()
{
    if (startTime != boost::posix_time::ptime())
        return  boost::posix_time::microsec_clock::local_time() - startTime;
    else
        return boost::posix_time::time_duration();
}

int64_t CommandProcessorStatistics::getCommandCount()
{
    return commandCount;
}

int64_t CommandProcessorStatistics::getAverageResponseTime()
{
    return (int64_t)averageResponseTime;
}

int64_t CommandProcessorStatistics::getOutgoingTraffic()
{
    return outgoingTraffic;
}

int64_t CommandProcessorStatistics::getIncomingTraffic()
{
    return incomingTraffic;
}

int64_t CommandProcessorStatistics::getUnrepliedCommandCount()
{
    return unrepliedCommandCount;
}
