//
// Copyright © 2020 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "BackendProfiling.hpp"
#include <client/src/RegisterBackendCounters.hpp>

namespace arm
{

namespace pipe
{

std::unique_ptr<IRegisterBackendCounters>
    BackendProfiling::GetCounterRegistrationInterface(uint16_t currentMaxGlobalCounterID)
{
    return std::make_unique<RegisterBackendCounters>(
        RegisterBackendCounters(currentMaxGlobalCounterID, m_BackendId, m_ProfilingService));
}

std::unique_ptr<ISendTimelinePacket> BackendProfiling::GetSendTimelinePacket()
{
    return m_ProfilingService.GetSendTimelinePacket();
}

IProfilingGuidGenerator& BackendProfiling::GetProfilingGuidGenerator()
{
    // The profiling service is our Guid Generator.
    return m_ProfilingService;
}

void BackendProfiling::ReportCounters(const std::vector<Timestamp>& timestamps)
{
    for (const auto& timestampInfo : timestamps)
    {
        std::vector<CounterValue> backendCounterValues = timestampInfo.counterValues;
        for_each(backendCounterValues.begin(), backendCounterValues.end(), [&](CounterValue& backendCounterValue)
        {
            // translate the counterId to globalCounterId
            backendCounterValue.counterId = m_ProfilingService.GetCounterMappings().GetGlobalId(
                backendCounterValue.counterId, m_BackendId);
        });

        // Send Periodic Counter Capture Packet for the Timestamp
        m_ProfilingService.GetSendCounterPacket().SendPeriodicCounterCapturePacket(
            timestampInfo.timestamp, backendCounterValues);
    }
}

CounterStatus BackendProfiling::GetCounterStatus(uint16_t backendCounterId)
{
    uint16_t globalCounterId = m_ProfilingService.GetCounterMappings().GetGlobalId(backendCounterId, m_BackendId);
    CaptureData captureData = m_ProfilingService.GetCaptureData();

    CounterStatus counterStatus(backendCounterId, globalCounterId, false, 0);

    if (captureData.IsCounterIdInCaptureData(globalCounterId))
    {
        counterStatus.m_Enabled = true;
        counterStatus.m_SamplingRateInMicroseconds = captureData.GetCapturePeriod();
    }

    return counterStatus;
}

std::vector<CounterStatus> BackendProfiling::GetActiveCounters()
{
    CaptureData captureData = m_ProfilingService.GetCaptureData();

    const std::vector<uint16_t>& globalCounterIds = captureData.GetCounterIds();
    std::vector<CounterStatus> activeCounterIds;

    for (auto globalCounterId : globalCounterIds) {
        // Get pair of local counterId and backendId using globalCounterId
        const std::pair<uint16_t, std::string>& backendCounterIdPair =
                m_ProfilingService.GetCounterMappings().GetBackendId(globalCounterId);
        if (backendCounterIdPair.second == m_BackendId)
        {
            activeCounterIds.emplace_back(backendCounterIdPair.first,
                                          globalCounterId,
                                          true,
                                          captureData.GetCapturePeriod());
        }
    }

    return activeCounterIds;
}

bool BackendProfiling::IsProfilingEnabled() const
{
    return m_ProfilingService.IsProfilingEnabled();
}

}    // namespace pipe

}    // namespace arm
