//
// Copyright © 2019 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//
#include "DirectoryCaptureCommandHandler.hpp"

#include <armnn/BackendId.hpp>
#include "ProfilingUtils.hpp"

#include <atomic>
#include <iostream>

namespace armnn
{

namespace profiling
{

// Utils
uint32_t uint16_t_size = sizeof(uint16_t);
uint32_t uint32_t_size = sizeof(uint32_t);

void DirectoryCaptureCommandHandler::ParseData(const armnn::profiling::Packet& packet)
{
    uint16_t categoryRecordCount;
    uint16_t counterSetRecordCount;
    uint16_t deviceRecordCount;

    uint32_t offset = 0;

    if (packet.GetLength() < 8)
    {
        std::cout << "Counter directory packet received." << std::endl;
        return;
    }

    const unsigned char* data = packet.GetData();
    // Body header word 0:
    // 0:15  [16] reserved: all zeros
    offset += uint16_t_size;
    // 16:31 [16] device_records_count: number of entries in the device_records_pointer_table
    deviceRecordCount = profiling::ReadUint16(data, offset);
    offset += uint16_t_size;

    // Body header word 1:
    // 0:31 [32] device_records_pointer_table_offset: offset to the device_records_pointer_table
    // The offset is always zero here, as the device record pointer table field is always the first item in the pool
    offset += uint32_t_size;

    // Body header word 2:
    // 0:15  [16] reserved: all zeros
    offset += uint16_t_size;
    // 16:31 [16] counter_set_count: number of entries in the counter_set_pointer_table
    counterSetRecordCount = profiling::ReadUint16(data, offset);
    offset += uint16_t_size;

    // Body header word 3:
    // 0:31 [32] counter_set_pointer_table_offset: offset to the counter_set_pointer_table
    // counterPointerTableSetOffset = profiling::ReadUint32(data, offset);
    offset += uint32_t_size;

    // Body header word 4:
    // 0:15  [16] reserved: all zeros
    offset += uint16_t_size;
    // 16:31 [16] categories_count: number of entries in the categories_pointer_table
    categoryRecordCount = profiling::ReadUint16(data, offset);
    offset += uint16_t_size;

    // Body header word 5:
    // 0:31 [32] categories_pointer_table_offset: offset to the categories_pointer_table
    // categoriesPointerTableOffset = profiling::ReadUint32(data, offset);
    offset += uint32_t_size;

    std::vector<uint32_t> deviceRecordOffsets(deviceRecordCount);
    std::vector<uint32_t> counterSetOffsets(counterSetRecordCount);
    std::vector<uint32_t> categoryOffsets(categoryRecordCount);

    for (uint32_t i = 0; i < deviceRecordCount; ++i)
    {
        deviceRecordOffsets[i] = profiling::ReadUint32(data, offset);
        offset += uint32_t_size;
    }

    for (uint32_t i = 0; i < counterSetRecordCount; ++i)
    {
        counterSetOffsets[i] = profiling::ReadUint32(data, offset);
        offset += uint32_t_size;
    }

    for (uint32_t i = 0; i < categoryRecordCount; ++i)
    {
        categoryOffsets[i] = profiling::ReadUint32(data, offset);
        offset += uint32_t_size;
    }

    for (uint32_t deviceIndex = 0; deviceIndex < deviceRecordCount; ++deviceIndex)
    {
        uint32_t deviceRecordOffset = offset + deviceRecordOffsets[deviceIndex];
        // Device record word 0:
        // 0:15  [16] cores: the number of individual streams of counters for one or more cores of some device
        uint16_t deviceCores = profiling::ReadUint16(data, deviceRecordOffset);
        // 16:31 [16] deviceUid: the unique identifier for the device
        deviceRecordOffset += uint16_t_size;
        uint16_t deviceUid = profiling::ReadUint16(data, deviceRecordOffset);
        deviceRecordOffset += uint16_t_size;

        // Device record word 1:
        // Offset from the beginning of the device record pool to the name field.
        uint32_t nameOffset = profiling::ReadUint32(data, deviceRecordOffset);

        deviceRecordOffset += uint32_t_size;
        deviceRecordOffset += uint32_t_size;
        deviceRecordOffset += nameOffset;

        const std::string& deviceName             = GetStringNameFromBuffer(data, deviceRecordOffset);
        const Device* registeredDevice            = m_CounterDirectory.RegisterDevice(deviceName, deviceCores);
        m_UidTranslation[registeredDevice->m_Uid] = deviceUid;
    }

    for (uint32_t counterSetIndex = 0; counterSetIndex < counterSetRecordCount; ++counterSetIndex)
    {
        uint32_t counterSetOffset = offset + counterSetOffsets[counterSetIndex];

        // Counter set record word 0:
        // 0:15  [16] count: the number of counters which can be active in this set at any one time
        uint16_t counterSetCount = profiling::ReadUint16(data, counterSetOffset);
        counterSetOffset += uint16_t_size;

        // 16:31 [16] deviceUid: the unique identifier for the counter_set
        uint16_t counterSetUid = profiling::ReadUint16(data, counterSetOffset);
        counterSetOffset += uint16_t_size;

        // Counter set record word 1:
        // 0:31 [32] name_offset: offset from the beginning of the counter set pool to the name field
        // The offset is always zero here, as the name field is always the first (and only) item in the pool
        counterSetOffset += uint32_t_size;
        counterSetOffset += uint32_t_size;

        auto counterSet =
            m_CounterDirectory.RegisterCounterSet(GetStringNameFromBuffer(data, counterSetOffset), counterSetCount);
        m_UidTranslation[counterSet->m_Uid] = counterSetUid;
    }
    ReadCategoryRecords(data, offset, categoryOffsets);
}

void DirectoryCaptureCommandHandler::ReadCategoryRecords(const unsigned char* const data,
                                                         uint32_t offset,
                                                         std::vector<uint32_t> categoryOffsets)
{
    uint32_t categoryRecordCount = static_cast<uint32_t>(categoryOffsets.size());

    for (uint32_t categoryIndex = 0; categoryIndex < categoryRecordCount; ++categoryIndex)
    {
        uint32_t categoryRecordOffset = offset + categoryOffsets[categoryIndex];

        // Category record word 0:
        // 0:15  The deviceUid of a counter_set the category is associated with.
        // Set to zero if the category is NOT associated with a counter set.
        uint16_t counterSetUid = profiling::ReadUint16(data, categoryRecordOffset);
        categoryRecordOffset += uint16_t_size;

        // 16:31 The deviceUid of a device element which identifies some hardware device that the category belongs to.
        // Set to zero if the category is NOT associated with a device
        uint16_t deviceUid = profiling::ReadUint16(data, categoryRecordOffset);

        categoryRecordOffset += uint16_t_size;

        // Category record word 1:
        // 0:15 Reserved, value 0x0000.
        categoryRecordOffset += uint16_t_size;
        // 16:31 Number of events belonging to this category.
        uint32_t eventCount = profiling::ReadUint16(data, categoryRecordOffset);
        categoryRecordOffset += uint16_t_size;

        // Category record word 2
        // 0:31  Offset from the beginning of the category data pool to the event_pointer_table
        uint32_t eventPointerTableOffset = profiling::ReadUint32(data, categoryRecordOffset);
        categoryRecordOffset += uint32_t_size;

        // Category record word 3
        // 0:31 Offset from the beginning of the category data pool to the name field.
        uint32_t nameOffset = profiling::ReadUint32(data, categoryRecordOffset);
        categoryRecordOffset += uint32_t_size;

        std::vector<uint32_t> eventRecordsOffsets(eventCount);

        eventPointerTableOffset += categoryRecordOffset;

        for (uint32_t eventIndex = 0; eventIndex < eventCount; ++eventIndex)
        {
            eventRecordsOffsets[eventIndex] =
                profiling::ReadUint32(data, eventPointerTableOffset + uint32_t_size * eventIndex);
        }

        const std::vector<CounterDirectoryEventRecord>& eventRecords =
            ReadEventRecords(data, categoryRecordOffset, eventRecordsOffsets);
        categoryRecordOffset += uint32_t_size;

        const Category* category = m_CounterDirectory.RegisterCategory(
            GetStringNameFromBuffer(data, categoryRecordOffset + nameOffset), deviceUid, counterSetUid);
        for (auto& counter : eventRecords)
        {
            const Counter* registeredCounter = m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
                                                                                  counter.m_CounterUid,
                                                                                  category->m_Name,
                                                                                  counter.m_CounterClass,
                                                                                  counter.m_CounterInterpolation,
                                                                                  counter.m_CounterMultiplier,
                                                                                  counter.m_CounterName,
                                                                                  counter.m_CounterDescription,
                                                                                  counter.m_CounterUnits);
            m_UidTranslation[registeredCounter->m_Uid] = counter.m_CounterUid;
        }
    }
}

std::vector<CounterDirectoryEventRecord> DirectoryCaptureCommandHandler::ReadEventRecords(
    const unsigned char* data, uint32_t offset, std::vector<uint32_t> eventRecordsOffsets)
{
    uint32_t eventCount = static_cast<uint32_t>(eventRecordsOffsets.size());

    std::vector<CounterDirectoryEventRecord> eventRecords(eventCount);
    for (unsigned long i = 0; i < eventCount; ++i)
    {
        uint32_t eventRecordOffset = eventRecordsOffsets[i] + offset;

        // Event record word 0:
        // 0:15  [16] count_uid: unique ID for the counter. Must be unique across all counters in all categories
        eventRecords[i].m_CounterUid = profiling::ReadUint16(data, eventRecordOffset);
        eventRecordOffset += uint16_t_size;
        // 16:31 [16] max_counter_uid: if the device this event is associated with has more than one core and there
        //                             is one of these counters per core this value will be set to
        //                             (counter_uid + cores (from device_record)) - 1.
        //                             If there is only a single core then this value will be the same as
        //                             the counter_uid value
        eventRecords[i].m_MaxCounterUid = profiling::ReadUint16(data, eventRecordOffset);
        eventRecordOffset += uint16_t_size;

        // Event record word 1:
        // 0:15  [16] counter_set: UID of the counter_set this event is associated with. Set to zero if the event
        //                         is NOT associated with a counter_set
        eventRecords[i].m_DeviceUid = profiling::ReadUint16(data, eventRecordOffset);
        eventRecordOffset += uint16_t_size;

        // 16:31 [16] device: UID of the device this event is associated with. Set to zero if the event is NOT
        //                    associated with a device
        eventRecords[i].m_CounterSetUid = profiling::ReadUint16(data, eventRecordOffset);
        eventRecordOffset += uint16_t_size;

        // Event record word 2:
        // 0:15  [16] interpolation: type describing how to interpolate each data point in a stream of data points
        eventRecords[i].m_CounterClass = profiling::ReadUint16(data, eventRecordOffset);
        eventRecordOffset += uint16_t_size;

        // 16:31 [16] class: type describing how to treat each data point in a stream of data points
        eventRecords[i].m_CounterInterpolation = profiling::ReadUint16(data, eventRecordOffset);
        eventRecordOffset += uint16_t_size;

        // Event record word 3-4:
        // 0:63 [64] multiplier: internal data stream is represented as integer values, this allows scaling of
        //                       those values as if they are fixed point numbers. Zero is not a valid value
        uint32_t multiplier[2] = { 0u, 0u };

        multiplier[0] = profiling::ReadUint32(data, eventRecordOffset);
        eventRecordOffset += uint32_t_size;
        multiplier[1] = profiling::ReadUint32(data, eventRecordOffset);
        eventRecordOffset += uint32_t_size;

        std::memcpy(&eventRecords[i].m_CounterMultiplier, &multiplier, sizeof(multiplier));

        // Event record word 5:
        // 0:31 [32] name_eventRecordOffset: eventRecordOffset from the
        // beginning of the event record pool to the name field
        // The eventRecordOffset is always zero here, as the name field is always the first item in the pool
        eventRecordOffset += uint32_t_size;

        // Event record word 6:
        // 0:31 [32] description_eventRecordOffset: eventRecordOffset from the
        // beginning of the event record pool to the description field
        // The size of the name buffer in bytes
        uint32_t descriptionOffset = profiling::ReadUint32(data, eventRecordOffset);
        eventRecordOffset += uint32_t_size;

        // Event record word 7:
        // 0:31 [32] units_eventRecordOffset: (optional) eventRecordOffset from the
        // beginning of the event record pool to the units field.
        // An eventRecordOffset value of zero indicates this field is not provided
        uint32_t unitsOffset = profiling::ReadUint32(data, eventRecordOffset);
        eventRecordOffset += uint32_t_size;
        eventRecordOffset += uint32_t_size;

        eventRecords[i].m_CounterName = GetStringNameFromBuffer(data, eventRecordOffset);

        eventRecords[i].m_CounterDescription = GetStringNameFromBuffer(data, eventRecordOffset + descriptionOffset);

        eventRecords[i].m_CounterUnits = GetStringNameFromBuffer(data, eventRecordOffset + unitsOffset);
    }

    return eventRecords;
}

void DirectoryCaptureCommandHandler::operator()(const profiling::Packet& packet)
{
    if (!m_QuietOperation)    // Are we supposed to print to stdout?
    {
        std::cout << "Counter directory packet received." << std::endl;
    }

    // The ArmNN counter directory is static per ArmNN instance. Ensure we don't parse it a second time.
    if (!ParsedCounterDirectory())
    {
        ParseData(packet);
        m_AlreadyParsed = true;
    }

    if (!m_QuietOperation)
    {
        armnn::profiling::PrintCounterDirectory(m_CounterDirectory);
    }
}

const ICounterDirectory& DirectoryCaptureCommandHandler::GetCounterDirectory() const
{
    return m_CounterDirectory;
}

std::string DirectoryCaptureCommandHandler::GetStringNameFromBuffer(const unsigned char* const data, uint32_t offset)
{
    std::string deviceName;
    uint8_t nextChar = profiling::ReadUint8(data, offset);

    while (isprint(nextChar))
    {
        deviceName += static_cast<char>(nextChar);
        offset++;
        nextChar = profiling::ReadUint8(data, offset);
    }

    return deviceName;
}

}    // namespace profiling

}    // namespace armnn