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

#include "PeriodicCounterCapture.hpp"

#include <armnn/Logging.hpp>

#include <iostream>

namespace armnn
{

namespace profiling
{

void PeriodicCounterCapture::Start()
{
    // Check if the capture thread is already running
    if (m_IsRunning)
    {
        // The capture thread is already running
        return;
    }

    // Mark the capture thread as running
    m_IsRunning = true;

    // Keep the capture procedure going until the capture thread is signalled to stop
    m_KeepRunning.store(true);

    // Start the new capture thread.
    m_PeriodCaptureThread = std::thread(&PeriodicCounterCapture::Capture, this, std::ref(m_ReadCounterValues));
}

void PeriodicCounterCapture::Stop()
{
    // Signal the capture thread to stop
    m_KeepRunning.store(false);

    // Check that the capture thread is running
    if (m_PeriodCaptureThread.joinable())
    {
        // Wait for the capture thread to complete operations
        m_PeriodCaptureThread.join();
    }

    // Mark the capture thread as not running
    m_IsRunning = false;
}

CaptureData PeriodicCounterCapture::ReadCaptureData()
{
    return m_CaptureDataHolder.GetCaptureData();
}

void PeriodicCounterCapture::DispatchPeriodicCounterCapturePacket(
    const armnn::BackendId& backendId, const std::vector<Timestamp>& timestampValues)
{
    // Report counter values
    for (const auto timestampInfo : timestampValues)
    {
        std::vector<CounterValue> backendCounterValues = timestampInfo.counterValues;
        for_each(backendCounterValues.begin(), backendCounterValues.end(), [&](CounterValue& backendCounterValue)
        {
            // translate the counterId to globalCounterId
            backendCounterValue.counterId = m_CounterIdMap.GetGlobalId(backendCounterValue.counterId, backendId);
        });

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

void PeriodicCounterCapture::Capture(IReadCounterValues& readCounterValues)
{
    do
    {
        // Check if the current capture data indicates that there's data capture
        auto currentCaptureData = ReadCaptureData();
        const std::vector<uint16_t>& counterIds = currentCaptureData.GetCounterIds();
        const uint32_t capturePeriod = currentCaptureData.GetCapturePeriod();

        if (capturePeriod == 0)
        {
            // No data capture, wait the indicated capture period (milliseconds), if it is not zero
            std::this_thread::sleep_for(std::chrono::milliseconds(50u));
            continue;
        }

        if(counterIds.size() != 0)
        {
            std::vector<CounterValue> counterValues;

            auto numCounters = counterIds.size();
            counterValues.reserve(numCounters);

            // Create a vector of pairs of CounterIndexes and Values
            for (uint16_t index = 0; index < numCounters; ++index)
            {
                auto requestedId = counterIds[index];
                uint32_t counterValue = 0;
                try
                {
                    counterValue = readCounterValues.GetDeltaCounterValue(requestedId);
                }
                catch (const Exception& e)
                {
                    // Report the error and continue
                    ARMNN_LOG(warning) << "An error has occurred when getting a counter value: "
                                       << e.what();
                    continue;
                }

                counterValues.emplace_back(CounterValue {requestedId, counterValue });
            }

            // Send Periodic Counter Capture Packet for the Timestamp
            m_SendCounterPacket.SendPeriodicCounterCapturePacket(GetTimestamp(), counterValues);
        }

        // Report counter values for each active backend
        auto activeBackends = currentCaptureData.GetActiveBackends();
        for_each(activeBackends.begin(), activeBackends.end(), [&](const armnn::BackendId& backendId)
        {
            DispatchPeriodicCounterCapturePacket(
                backendId, m_BackendProfilingContexts.at(backendId)->ReportCounterValues());
        });

        // Wait the indicated capture period (microseconds)
        std::this_thread::sleep_for(std::chrono::microseconds(capturePeriod));
    }
    while (m_KeepRunning.load());
}

} // namespace profiling

} // namespace armnn