///////////////////////////////////////////////////////////////
//
// CPerfStatEventPacketUsageImpl::GetStats
//
//
//
///////////////////////////////////////////////////////////////
void CPerfStatEventPacketUsageImpl::GetStats ( CPerfStatResult* pResult, const std::map < SString, int >& strOptionMap, const SString& strFilter )
{
    m_TimeSinceGetStats.Reset ();
    m_bEnabled = true;
    MaybeRecordStats();

    //
    // Set option flags
    //
    bool bHelp = MapContains ( strOptionMap, "h" );

    //
    // Process help
    //
    if ( bHelp )
    {
        pResult->AddColumn ( "Event Packet usage help" );
        pResult->AddRow ()[0] ="Option h - This help";
        return;
    }

    // Add columns
    pResult->AddColumn ( "Type" );
    pResult->AddColumn ( "Name" );
    pResult->AddColumn ( "msgs/sec" );
    pResult->AddColumn ( "5 sec.msgs" );

    // Fill rows
    for ( uint i = 0 ; i < m_EventUsageSortedList.size() && i < 30 ; i++ )
    {
        const SEventUsage& usage = m_EventUsageSortedList[i];

        // Add row
        SString* row = pResult->AddRow ();

        SString strType;
        if ( usage.iEventOut )
            strType += "Event ";
        if ( usage.iElementDataOut )
            strType += "ElementData ";
        if ( usage.iElementDataRelay )
            strType += "ElementData(Relay) ";

        int c = 0;
        row[c++] = strType;
        row[c++] = usage.strName;
        row[c++] = SString ( "%d", ( usage.iTotal + 4 ) / 5 );
        row[c++] = SString ( "%d", usage.iTotal );
    }
}
///////////////////////////////////////////////////////////////
//
// CPerfStatRPCPacketUsageImpl::GetStats
//
//
//
///////////////////////////////////////////////////////////////
void CPerfStatRPCPacketUsageImpl::GetStats(CPerfStatResult* pResult, const std::map<SString, int>& strOptionMap, const SString& strFilter)
{
    m_TimeSinceGetStats.Reset();
    MaybeRecordStats();

    //
    // Set option flags
    //
    bool bHelp = MapContains(strOptionMap, "h");

    //
    // Process help
    //
    if (bHelp)
    {
        pResult->AddColumn("RPC Packet usage help");
        pResult->AddRow()[0] = "Option h - This help";
        return;
    }

    // Add columns
    pResult->AddColumn("Packet type");
    pResult->AddColumn("Incoming.msgs/sec");
    pResult->AddColumn("Incoming.bytes/sec");
    pResult->AddColumn("Incoming.cpu");
    pResult->AddColumn("Outgoing.msgs/sec");
    pResult->AddColumn("Outgoing.bytes/sec");
    pResult->AddColumn("Outgoing.cpu");

    if (m_iStatsCleared)
    {
        pResult->AddRow()[0] = "Sampling... Please wait";
    }

    long long llTickCountNow = CTickCount::Now().ToLongLong();

    // Fill rows
    for (uint i = 0; i < 256; i++)
    {
        // Calc incoming delta values
        SPacketStat statInDelta;
        {
            const SRPCPacketStat& statInPrev = m_PrevPacketStatsIn[i];
            const SRPCPacketStat& statInNow = m_PacketStatsIn[i];
            statInDelta.iCount = statInNow.iCount - statInPrev.iCount;
            statInDelta.iTotalBytes = statInNow.iTotalBytes - statInPrev.iTotalBytes;
            // statInDelta.totalTime   = statInNow.totalTime - statInPrev.totalTime;
        }

        if (!statInDelta.iCount)
        {
            // Once displayed, keep a row displayed for at least 20 seconds
            if (llTickCountNow - m_ShownPacketStatsIn[i] > 20000)
                continue;
        }
        else
        {
            m_ShownPacketStatsIn[i] = llTickCountNow;
        }

        // Add row
        SString* row = pResult->AddRow();

        int c = 0;
        // Turn "CRPCFunctions::PLAYER_WEAPON" into "64_Player_weapon"
        SString strPacketDesc = EnumToString((CRPCFunctions::eRPCFunctions)i).SplitRight("CRPCFunctions::", NULL, -1).ToLower();
        row[c++] = SString("%d_", i) + strPacketDesc.Left(1).ToUpper() + strPacketDesc.SubStr(1);

        if (statInDelta.iCount)
        {
            row[c++] = SString("%d", (statInDelta.iCount + 4) / 5);
            row[c++] = CPerfStatManager::GetScaledByteString((statInDelta.iTotalBytes + 4) / 5);
            row[c++] = "n/a";
        }
        else
        {
            row[c++] = "-";
            row[c++] = "-";
            row[c++] = "-";
        }

        row[c++] = "-";
        row[c++] = "-";
        row[c++] = "-";
    }

    // Fill rows
    for (uint i = 0; i < 256; i++)
    {
        // Calc outgoing delta values
        SRPCPacketStat statOutDelta;
        {
            const SRPCPacketStat& statOutPrev = m_PrevPacketStatsOut[i];
            const SRPCPacketStat& statOutNow = m_PacketStatsOut[i];
            statOutDelta.iCount = statOutNow.iCount - statOutPrev.iCount;
            statOutDelta.iTotalBytes = statOutNow.iTotalBytes - statOutPrev.iTotalBytes;
        }

        if (!statOutDelta.iCount)
        {
            // Once displayed, keep a row displayed for at least 20 seconds
            if (llTickCountNow - m_ShownPacketStatsOut[i] > 20000)
                continue;
        }
        else
        {
            m_ShownPacketStatsOut[i] = llTickCountNow;
        }

        // Add row
        SString* row = pResult->AddRow();

        int c = 0;
        // Turn "SET_WEAPON_OWNER" into "64_Set_weapon_owner"
        SString strPacketDesc = EnumToString((eElementRPCFunctions)i).ToLower();
        row[c++] = SString("%d_", i) + strPacketDesc.Left(1).ToUpper() + strPacketDesc.SubStr(1);

        row[c++] = "-";
        row[c++] = "-";
        row[c++] = "-";

        if (statOutDelta.iCount)
        {
            row[c++] = SString("%d", (statOutDelta.iCount + 4) / 5);
            row[c++] = CPerfStatManager::GetScaledByteString((statOutDelta.iTotalBytes + 4) / 5);
            row[c++] = "n/a";
        }
        else
        {
            row[c++] = "-";
            row[c++] = "-";
            row[c++] = "-";
        }
    }
}
///////////////////////////////////////////////////////////////
//
// CPerfStatRPCPacketUsageImpl::DoPulse
//
//
//
///////////////////////////////////////////////////////////////
void CPerfStatRPCPacketUsageImpl::DoPulse(void)
{
    MaybeRecordStats();
}
///////////////////////////////////////////////////////////////
//
// CPerfStatPacketUsageImpl::GetStats
//
//
//
///////////////////////////////////////////////////////////////
void CPerfStatPacketUsageImpl::GetStats(CPerfStatResult* pResult, const std::map<SString, int>& strOptionMap, const SString& strFilter)
{
    m_TimeSinceGetStats.Reset();
    MaybeRecordStats();

    //
    // Set option flags
    //
    bool bHelp = MapContains(strOptionMap, "h");

    //
    // Process help
    //
    if (bHelp)
    {
        pResult->AddColumn("Packet usage help");
        pResult->AddRow()[0] = "Option h - This help";
        return;
    }

    // Add columns
    pResult->AddColumn("Packet type");
    pResult->AddColumn("Incoming.msgs/sec");
    pResult->AddColumn("Incoming.bytes/sec");
    pResult->AddColumn("Incoming.logic cpu");
    pResult->AddColumn("Outgoing.msgs/sec");
    pResult->AddColumn("Outgoing.bytes/sec");
    pResult->AddColumn("Outgoing.msgs share");

    if (m_iStatsCleared)
    {
        pResult->AddRow()[0] = "Sampling... Please wait";
    }

    // Calc msgs grand total for percent calculation
    int iOutDeltaCountTotal = 0;
    for (uint i = 0; i < 256; i++)
    {
        const SPacketStat& statOutPrev = m_PrevPacketStats[CNetServer::STATS_OUTGOING_TRAFFIC][i];
        const SPacketStat& statOutNow = m_PacketStats[CNetServer::STATS_OUTGOING_TRAFFIC][i];
        iOutDeltaCountTotal += statOutNow.iCount - statOutPrev.iCount;
    }

    long long llTickCountNow = CTickCount::Now().ToLongLong();
    // Fill rows
    for (uint i = 0; i < 256; i++)
    {
        // Calc incoming delta values
        SPacketStat statInDelta;
        {
            const SPacketStat& statInPrev = m_PrevPacketStats[CNetServer::STATS_INCOMING_TRAFFIC][i];
            const SPacketStat& statInNow = m_PacketStats[CNetServer::STATS_INCOMING_TRAFFIC][i];
            statInDelta.iCount = statInNow.iCount - statInPrev.iCount;
            statInDelta.iTotalBytes = statInNow.iTotalBytes - statInPrev.iTotalBytes;
            statInDelta.totalTime = statInNow.totalTime - statInPrev.totalTime;
        }

        // Calc outgoing delta values
        SPacketStat statOutDelta;
        {
            const SPacketStat& statOutPrev = m_PrevPacketStats[CNetServer::STATS_OUTGOING_TRAFFIC][i];
            const SPacketStat& statOutNow = m_PacketStats[CNetServer::STATS_OUTGOING_TRAFFIC][i];
            statOutDelta.iCount = statOutNow.iCount - statOutPrev.iCount;
            statOutDelta.iTotalBytes = statOutNow.iTotalBytes - statOutPrev.iTotalBytes;
            statOutDelta.totalTime = statOutNow.totalTime - statOutPrev.totalTime;
        }

        if (!statInDelta.iCount && !statOutDelta.iCount)
        {
            // Once displayed, keep a row displayed for at least 20 seconds
            if (llTickCountNow - m_ShownPacketStats[i] > 20000)
                continue;
        }
        else
        {
            m_ShownPacketStats[i] = llTickCountNow;
        }

        // Add row
        SString* row = pResult->AddRow();

        int c = 0;
        // Turn "PACKET_ID_PED_SYNC" into "64_Ped_sync"
        SString strPacketDesc = EnumToString((ePacketID)i).SplitRight("PACKET_ID", NULL, -1).ToLower();
        row[c++] = SString("%d", i) + strPacketDesc.Left(2).ToUpper() + strPacketDesc.SubStr(2);
        if (statInDelta.iCount)
        {
            row[c++] = SString("%d", (statInDelta.iCount + 4) / 5);
            row[c++] = CPerfStatManager::GetScaledByteString((statInDelta.iTotalBytes + 4) / 5);
            row[c++] = SString("%2.2f%%",
                               statInDelta.totalTime / 50000.f);            // Number of microseconds in sample period ( 5sec * 1000000 ) into percent ( * 100 )
        }
        else
        {
            row[c++] = "-";
            row[c++] = "-";
            row[c++] = "-";
        }

        if (statOutDelta.iCount)
        {
            row[c++] = SString("%d", (statOutDelta.iCount + 4) / 5);
            row[c++] = CPerfStatManager::GetScaledByteString((statOutDelta.iTotalBytes + 4) / 5);
            row[c++] = SString("%d%%", (int)(statOutDelta.iCount * 100 / iOutDeltaCountTotal));
        }
        else
        {
            row[c++] = "-";
            row[c++] = "-";
            row[c++] = "-";
        }
    }
}
///////////////////////////////////////////////////////////////
//
// CClientPerfStatPacketUsageImpl::DoPulse
//
//
//
///////////////////////////////////////////////////////////////
void CClientPerfStatPacketUsageImpl::DoPulse ( void )
{
    MaybeRecordStats();
}
///////////////////////////////////////////////////////////////
//
// CPerfStatEventPacketUsageImpl::DoPulse
//
//
//
///////////////////////////////////////////////////////////////
void CPerfStatEventPacketUsageImpl::DoPulse()
{
    MaybeRecordStats();
}