//
// 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 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));
        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