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

#include "ClBackendContext.hpp"
#include "ClContextControl.hpp"

#include <armnn/Logging.hpp>

#include <arm_compute/core/CL/OpenCL.h>
#include <arm_compute/core/CL/CLKernelLibrary.h>
#include <arm_compute/runtime/CL/CLScheduler.h>
#include <arm_compute/runtime/CL/CLTunerTypes.h>

#include <boost/polymorphic_cast.hpp>

namespace armnn
{

struct ClBackendContext::ClContextControlWrapper
{
    ClContextControlWrapper(arm_compute::CLTuner* tuner,
                            bool profilingEnabled)
        : m_ClContextControl(tuner, profilingEnabled)
    {}

    bool Sync()
    {
        if (arm_compute::CLScheduler::get().context()() != NULL)
        {
            // Waits for all queued CL requests to finish before unloading the network they may be using.
            try
            {
                // Coverity fix: arm_compute::CLScheduler::sync() may throw an exception of type cl::Error.
                arm_compute::CLScheduler::get().sync();
            }
            catch (const cl::Error&)
            {
                ARMNN_LOG(warning) << "Runtime::UnloadNetwork(): an error occurred while waiting for "
                                      "the queued CL requests to finish";
                return false;
            }
        }

        return true;
    }

    void ClearClCache()
    {
        if (arm_compute::CLScheduler::get().context()() != NULL)
        {
            // There are no loaded networks left, so clear the CL cache to free up memory
            m_ClContextControl.ClearClCache();
        }
    }

    ClContextControl m_ClContextControl;
};

std::string LowerString(std::string value)
{
    std::transform(value.begin(), value.end(), value.begin(),
                   [](unsigned char c){ return std::tolower(c); });

    return value;
}

enum class TuningLevel
{
    None,
    Rapid,
    Normal,
    Exhaustive
};


TuningLevel ParseTuningLevel(const BackendOptions::Var& value, TuningLevel defaultValue)
{
    if (value.IsInt())
    {
        int v = value.IsInt();
        if (v > static_cast<int>(TuningLevel::Exhaustive) ||
            v < static_cast<int>(TuningLevel::None))
        {
            ARMNN_LOG(warning) << "Invalid GpuAcc tuning level ("<< v << ") selected. "
                                  "Using default(" << static_cast<int>(defaultValue) << ")";
        } else
        {
            return static_cast<TuningLevel>(v);
        }
    }
    return defaultValue;
}

bool ParseBoolean(const BackendOptions::Var& value, bool defaultValue)
{
    if (value.IsBool())
    {
        return value.AsBool();
    }

    return defaultValue;
}

std::string ParseFile(const BackendOptions::Var& value, std::string defaultValue)
{
    if (value.IsString())
    {
        return value.AsString();
    }
    return defaultValue;
}

template <typename F>
void ParseOptions(const std::vector<BackendOptions>& options, BackendId backend, F f)
{
    for (auto optionsGroup : options)
    {
        if (optionsGroup.GetBackendId() == backend)
        {
            for (size_t i=0; i < optionsGroup.GetOptionCount(); i++)
            {
                const BackendOptions::BackendOption option = optionsGroup.GetOption(i);
                f(option.GetName(), option.GetValue());
            }
        }
    }
}

void ConfigureTuner(arm_compute::CLTuner &tuner, TuningLevel level)
{
    tuner.set_tune_new_kernels(true); // Turn on tuning initially.

    switch (level)
    {
        case TuningLevel::Rapid:
            tuner.set_tuner_mode(arm_compute::CLTunerMode::RAPID);
            break;
        case TuningLevel::Normal:
            tuner.set_tuner_mode(arm_compute::CLTunerMode::NORMAL);
            break;
        case TuningLevel::Exhaustive:
            tuner.set_tuner_mode(arm_compute::CLTunerMode::EXHAUSTIVE);
            break;
        case TuningLevel::None:
        default:
            tuner.set_tune_new_kernels(false); // Turn off tuning. Set to "use" only mode.
            break;
    }
}

ClBackendContext::ClBackendContext(const IRuntime::CreationOptions& options)
    : IBackendContext(options)
    , m_TuningFile()
{
    bool kernelProfiling = options.m_EnableGpuProfiling;

    arm_compute::CLTuner* tuner = nullptr;
    bool useLegacyTunerAPI = options.m_GpuAccTunedParameters.get() != nullptr;
    if (useLegacyTunerAPI)
    {
        auto clTunerParams = boost::polymorphic_downcast<ClTunedParameters*>(
                                options.m_GpuAccTunedParameters.get());
        tuner = &clTunerParams->m_Tuner;

        if (tuner)
        {
            auto ConvertTuningLevel = [](IGpuAccTunedParameters::TuningLevel level,
                                         armnn::IGpuAccTunedParameters::Mode mode)
                {
                    if (mode == armnn::IGpuAccTunedParameters::Mode::UseTunedParameters)
                    {
                        return TuningLevel::None;
                    }

                    switch(level)
                    {
                        case IGpuAccTunedParameters::TuningLevel::Rapid:
                            return TuningLevel::Rapid;
                        case IGpuAccTunedParameters::TuningLevel::Normal:
                            return TuningLevel::Normal;
                        case IGpuAccTunedParameters::TuningLevel::Exhaustive:
                            return TuningLevel::Exhaustive;
                        default:
                        {
                            BOOST_ASSERT_MSG(false, "Tuning level not recognised.");
                            return TuningLevel::None;
                        }
                    }
                };

            TuningLevel tuningLevel = ConvertTuningLevel(clTunerParams->m_TuningLevel, clTunerParams->m_Mode);
            ConfigureTuner(*tuner, tuningLevel);
        }
    }
    else //New backend options API
    {
        const TuningLevel defaultTuningLevel = TuningLevel::None;
        auto tuningLevel = defaultTuningLevel;

        ParseOptions(options.m_BackendOptions, "GpuAcc", [&](std::string name, const BackendOptions::Var& value)
            {
                if (name == "KernelProfilingEnabled")
                {
                    kernelProfiling |= ParseBoolean(value, false);
                } else if (name == "TuningFile")
                {
                    m_TuningFile = ParseFile(value, "");
                } else if (name == "TuningLevel")
                {
                    tuningLevel = ParseTuningLevel(value, defaultTuningLevel);
                }
            });

        // Create the tuner, in tuning mode initially.
        m_Tuner = std::make_unique<arm_compute::CLTuner>(true);

        ConfigureTuner(*(m_Tuner.get()), tuningLevel);

        if (!m_TuningFile.empty())
        {
            try
            {
                m_Tuner->load_from_file(m_TuningFile.c_str());
            } catch (const std::exception& e)
            {
                ARMNN_LOG(warning) << "Could not load GpuAcc tuner data file.";
            }

            tuner = m_Tuner.get();
        }
    }

    m_ClContextControlWrapper = std::make_unique<ClContextControlWrapper>(
            tuner,
            kernelProfiling
        );
}

bool ClBackendContext::BeforeLoadNetwork(NetworkId)
{
    return true;
}

bool ClBackendContext::AfterLoadNetwork(NetworkId networkId)
{
    {
        std::lock_guard<std::mutex> lockGuard(m_Mutex);
        m_NetworkIds.insert(networkId);
    }
    return true;
}

bool ClBackendContext::BeforeUnloadNetwork(NetworkId)
{
    return m_ClContextControlWrapper->Sync();
}

bool ClBackendContext::AfterUnloadNetwork(NetworkId networkId)
{
    bool clearCache = false;
    {
        std::lock_guard<std::mutex> lockGuard(m_Mutex);
        m_NetworkIds.erase(networkId);
        clearCache = m_NetworkIds.empty();
    }

    if (clearCache)
    {
        m_ClContextControlWrapper->ClearClCache();
    }

    return true;
}

ClBackendContext::~ClBackendContext()
{
    if (m_Tuner && !m_TuningFile.empty())
    {
        try
        {
            m_Tuner->save_to_file(m_TuningFile.c_str());
        }
        catch(const std::exception& e)
        {
            ARMNN_LOG(warning) << "Could not save GpuAcc tuner data to file " << m_TuningFile;
        }
    }
}

} // namespace armnn