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

#pragma once

#include <armnn/profiling/ILocalPacketHandler.hpp>
#include "DirectoryCaptureCommandHandler.hpp"
#include "IProfilingConnection.hpp"
#include "ProfilingUtils.hpp"
#include "Runtime.hpp"

#include <common/include/Packet.hpp>

#include <atomic>
#include <condition_variable>
#include <fstream>
#include <mutex>
#include <queue>
#include <thread>

namespace armnn
{

namespace profiling
{

// forward declaration
class FileOnlyProfilingConnection;

class StreamMetaDataProcessor : public ILocalPacketHandler
{
public:
    explicit StreamMetaDataProcessor(FileOnlyProfilingConnection* fileOnlyProfilingConnection) :
            m_FileOnlyProfilingConnection(fileOnlyProfilingConnection),
            m_MetaDataPacketHeader(ConstructHeader(0, 0)) {};

    std::vector<uint32_t> GetHeadersAccepted() override;

    void HandlePacket(const arm::pipe::Packet& packet) override;

private:
    FileOnlyProfilingConnection* m_FileOnlyProfilingConnection;
    uint32_t m_MetaDataPacketHeader;

    static uint32_t ToUint32(const unsigned char* data, TargetEndianness endianness);
};

class FileOnlyProfilingConnection : public IProfilingConnection, public IInternalProfilingConnection
{
public:
    explicit FileOnlyProfilingConnection(const Runtime::CreationOptions::ExternalProfilingOptions& options)
        : m_Options(options)
        , m_Endianness(TargetEndianness::LeWire)    // Set a sensible default.
                                                    // StreamMetaDataProcessor will set a real value.
        , m_IsRunning(false)
        , m_KeepRunning(false)
        , m_Timeout(1000)
    {
        // add the StreamMetaDataProcessor
        auto streamMetaDataProcessor = std::make_shared<StreamMetaDataProcessor>(this);
        AddLocalPacketHandler(streamMetaDataProcessor);
        // and any additional ones added by the users
        for (const ILocalPacketHandlerSharedPtr& localPacketHandler : options.m_LocalPacketHandlers)
        {
            AddLocalPacketHandler(localPacketHandler);
        }
        if (!m_PacketHandlers.empty())
        {
            StartProcessingThread();
        }
        // NOTE: could add timeout to the external profiling options
    };

    ~FileOnlyProfilingConnection() override;

    bool IsOpen() const override;

    void Close() override;

    // This is effectively receiving a data packet from ArmNN.
    bool WritePacket(const unsigned char* buffer, uint32_t length) override;

    // Sending a packet back to ArmNN.
    arm::pipe::Packet ReadPacket(uint32_t timeout) override;

    void SetEndianess(const TargetEndianness& endianness) override //IInternalProfilingConnection
    {
        m_Endianness = endianness;
    }

    void ReturnPacket(arm::pipe::Packet& packet) override; //IInternalProfilingConnection

private:
    void AddLocalPacketHandler(ILocalPacketHandlerSharedPtr localPacketHandler);
    void StartProcessingThread();
    void ClearReadableList();
    void DispatchPacketToHandlers(const arm::pipe::Packet& packet);

    void Fail(const std::string& errorMessage);

    void ForwardPacketToHandlers(arm::pipe::Packet& packet);
    void ServiceLocalHandlers();

    Runtime::CreationOptions::ExternalProfilingOptions m_Options;
    std::queue<arm::pipe::Packet> m_PacketQueue;
    TargetEndianness m_Endianness;

    std::mutex m_PacketAvailableMutex;
    std::condition_variable m_ConditionPacketAvailable;

    std::vector<ILocalPacketHandlerSharedPtr> m_PacketHandlers;
    std::map<uint32_t, std::vector<ILocalPacketHandlerSharedPtr>> m_IndexedHandlers;
    std::vector<ILocalPacketHandlerSharedPtr> m_UniversalHandlers;

    // List of readable packets for the local packet handlers
    std::queue<arm::pipe::Packet> m_ReadableList;
    // Mutex and condition variable for the readable packet list
    std::mutex m_ReadableMutex;
    std::condition_variable m_ConditionPacketReadable;
    // thread that takes items from the readable list and dispatches them
    // to the handlers.
    std::thread m_LocalHandlersThread;
    // atomic booleans that control the operation of the local handlers thread
    std::atomic<bool> m_IsRunning;
    std::atomic<bool> m_KeepRunning;
    int m_Timeout;
};

}    // namespace profiling

}    // namespace armnn