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

#pragma once

#include <armnn/IRuntime.hpp>
#include <test/TensorHelpers.hpp>

#include <Network.hpp>
#include <VerificationHelpers.hpp>

#include <fmt/format.h>

#include <iomanip>
#include <string>

namespace armnnUtils
{

template<typename TParser>
struct ParserPrototxtFixture
{
    ParserPrototxtFixture()
        : m_Parser(TParser::Create())
        , m_Runtime(armnn::IRuntime::Create(armnn::IRuntime::CreationOptions()))
        , m_NetworkIdentifier(-1)
    {
    }

    /// Parses and loads the network defined by the m_Prototext string.
    /// @{
    void SetupSingleInputSingleOutput(const std::string& inputName, const std::string& outputName);
    void SetupSingleInputSingleOutput(const armnn::TensorShape& inputTensorShape,
        const std::string& inputName,
        const std::string& outputName);
    void SetupSingleInputSingleOutput(const armnn::TensorShape& inputTensorShape,
                                      const armnn::TensorShape& outputTensorShape,
                                      const std::string& inputName,
                                      const std::string& outputName);
    void Setup(const std::map<std::string, armnn::TensorShape>& inputShapes,
        const std::vector<std::string>& requestedOutputs);
    void Setup();
    armnn::IOptimizedNetworkPtr SetupOptimizedNetwork(
        const std::map<std::string,armnn::TensorShape>& inputShapes,
        const std::vector<std::string>& requestedOutputs);
    /// @}

    /// Executes the network with the given input tensor and checks the result against the given output tensor.
    /// This overload assumes that the network has a single input and a single output.
    template <std::size_t NumOutputDimensions>
    void RunTest(const std::vector<float>& inputData, const std::vector<float>& expectedOutputData);

    /// Executes the network with the given input tensor and checks the result against the given output tensor.
    /// Calls RunTest with output type of uint8_t for checking comparison operators.
    template <std::size_t NumOutputDimensions>
    void RunComparisonTest(const std::map<std::string, std::vector<float>>& inputData,
                           const std::map<std::string, std::vector<uint8_t>>& expectedOutputData);

    /// Executes the network with the given input tensors and checks the results against the given output tensors.
    /// This overload supports multiple inputs and multiple outputs, identified by name.
    template <std::size_t NumOutputDimensions, typename T = float>
    void RunTest(const std::map<std::string, std::vector<float>>& inputData,
                 const std::map<std::string, std::vector<T>>& expectedOutputData);

    std::string                                         m_Prototext;
    std::unique_ptr<TParser, void(*)(TParser* parser)>  m_Parser;
    armnn::IRuntimePtr                                  m_Runtime;
    armnn::NetworkId                                    m_NetworkIdentifier;

    /// If the single-input-single-output overload of Setup() is called, these will store the input and output name
    /// so they don't need to be passed to the single-input-single-output overload of RunTest().
    /// @{
    std::string m_SingleInputName;
    std::string m_SingleOutputName;
    /// @}

    /// This will store the output shape so it don't need to be passed to the single-input-single-output overload
    /// of RunTest().
    armnn::TensorShape m_SingleOutputShape;
};

template<typename TParser>
void ParserPrototxtFixture<TParser>::SetupSingleInputSingleOutput(const std::string& inputName,
    const std::string& outputName)
{
    // Stores the input and output name so they don't need to be passed to the single-input-single-output RunTest().
    m_SingleInputName = inputName;
    m_SingleOutputName = outputName;
    Setup({ }, { outputName });
}

template<typename TParser>
void ParserPrototxtFixture<TParser>::SetupSingleInputSingleOutput(const armnn::TensorShape& inputTensorShape,
    const std::string& inputName,
    const std::string& outputName)
{
    // Stores the input and output name so they don't need to be passed to the single-input-single-output RunTest().
    m_SingleInputName = inputName;
    m_SingleOutputName = outputName;
    Setup({ { inputName, inputTensorShape } }, { outputName });
}

template<typename TParser>
void ParserPrototxtFixture<TParser>::SetupSingleInputSingleOutput(const armnn::TensorShape& inputTensorShape,
                                                                  const armnn::TensorShape& outputTensorShape,
                                                                  const std::string& inputName,
                                                                  const std::string& outputName)
{
    // Stores the input name, the output name and the output tensor shape
    // so they don't need to be passed to the single-input-single-output RunTest().
    m_SingleInputName = inputName;
    m_SingleOutputName = outputName;
    m_SingleOutputShape = outputTensorShape;
    Setup({ { inputName, inputTensorShape } }, { outputName });
}

template<typename TParser>
void ParserPrototxtFixture<TParser>::Setup(const std::map<std::string, armnn::TensorShape>& inputShapes,
    const std::vector<std::string>& requestedOutputs)
{
    std::string errorMessage;

    armnn::INetworkPtr network =
        m_Parser->CreateNetworkFromString(m_Prototext.c_str(), inputShapes, requestedOutputs);
    auto optimized = Optimize(*network, { armnn::Compute::CpuRef }, m_Runtime->GetDeviceSpec());
    armnn::Status ret = m_Runtime->LoadNetwork(m_NetworkIdentifier, move(optimized), errorMessage);
    if (ret != armnn::Status::Success)
    {
        throw armnn::Exception(fmt::format("LoadNetwork failed with error: '{0}' {1}",
                                           errorMessage,
                                           CHECK_LOCATION().AsString()));
    }
}

template<typename TParser>
void ParserPrototxtFixture<TParser>::Setup()
{
    std::string errorMessage;

    armnn::INetworkPtr network =
        m_Parser->CreateNetworkFromString(m_Prototext.c_str());
    auto optimized = Optimize(*network, { armnn::Compute::CpuRef }, m_Runtime->GetDeviceSpec());
    armnn::Status ret = m_Runtime->LoadNetwork(m_NetworkIdentifier, move(optimized), errorMessage);
    if (ret != armnn::Status::Success)
    {
        throw armnn::Exception(fmt::format("LoadNetwork failed with error: '{0}' {1}",
                                           errorMessage,
                                           CHECK_LOCATION().AsString()));
    }
}

template<typename TParser>
armnn::IOptimizedNetworkPtr ParserPrototxtFixture<TParser>::SetupOptimizedNetwork(
    const std::map<std::string,armnn::TensorShape>& inputShapes,
    const std::vector<std::string>& requestedOutputs)
{
    armnn::INetworkPtr network =
        m_Parser->CreateNetworkFromString(m_Prototext.c_str(), inputShapes, requestedOutputs);
    auto optimized = Optimize(*network, { armnn::Compute::CpuRef }, m_Runtime->GetDeviceSpec());
    return optimized;
}

template<typename TParser>
template <std::size_t NumOutputDimensions>
void ParserPrototxtFixture<TParser>::RunTest(const std::vector<float>& inputData,
                                             const std::vector<float>& expectedOutputData)
{
    RunTest<NumOutputDimensions>({ { m_SingleInputName, inputData } }, { { m_SingleOutputName, expectedOutputData } });
}

template<typename TParser>
template <std::size_t NumOutputDimensions>
void ParserPrototxtFixture<TParser>::RunComparisonTest(const std::map<std::string, std::vector<float>>& inputData,
                                                       const std::map<std::string, std::vector<uint8_t>>&
                                                       expectedOutputData)
{
    RunTest<NumOutputDimensions, uint8_t>(inputData, expectedOutputData);
}

template<typename TParser>
template <std::size_t NumOutputDimensions, typename T>
void ParserPrototxtFixture<TParser>::RunTest(const std::map<std::string, std::vector<float>>& inputData,
    const std::map<std::string, std::vector<T>>& expectedOutputData)
{
    // Sets up the armnn input tensors from the given vectors.
    armnn::InputTensors inputTensors;
    for (auto&& it : inputData)
    {
        armnn::BindingPointInfo bindingInfo = m_Parser->GetNetworkInputBindingInfo(it.first);
        inputTensors.push_back({ bindingInfo.first, armnn::ConstTensor(bindingInfo.second, it.second.data()) });
    }

    // Allocates storage for the output tensors to be written to and sets up the armnn output tensors.
    std::map<std::string, boost::multi_array<T, NumOutputDimensions>> outputStorage;
    armnn::OutputTensors outputTensors;
    for (auto&& it : expectedOutputData)
    {
        armnn::BindingPointInfo bindingInfo = m_Parser->GetNetworkOutputBindingInfo(it.first);
        outputStorage.emplace(it.first, MakeTensor<T, NumOutputDimensions>(bindingInfo.second));
        outputTensors.push_back(
            { bindingInfo.first, armnn::Tensor(bindingInfo.second, outputStorage.at(it.first).data()) });
    }

    m_Runtime->EnqueueWorkload(m_NetworkIdentifier, inputTensors, outputTensors);

    // Compares each output tensor to the expected values.
    for (auto&& it : expectedOutputData)
    {
        armnn::BindingPointInfo bindingInfo = m_Parser->GetNetworkOutputBindingInfo(it.first);
        if (bindingInfo.second.GetNumElements() != it.second.size())
        {
            throw armnn::Exception(fmt::format("Output tensor {0} is expected to have {1} elements. "
                                               "{2} elements supplied. {3}",
                                               it.first,
                                               bindingInfo.second.GetNumElements(),
                                               it.second.size(),
                                               CHECK_LOCATION().AsString()));
        }

        // If the expected output shape is set, the output tensor checks will be carried out.
        if (m_SingleOutputShape.GetNumDimensions() != 0)
        {

            if (bindingInfo.second.GetShape().GetNumDimensions() == NumOutputDimensions &&
                bindingInfo.second.GetShape().GetNumDimensions() == m_SingleOutputShape.GetNumDimensions())
            {
                for (unsigned int i = 0; i < m_SingleOutputShape.GetNumDimensions(); ++i)
                {
                    if (m_SingleOutputShape[i] != bindingInfo.second.GetShape()[i])
                    {
                        // This exception message could not be created by fmt:format because of an oddity in
                        // the operator << of TensorShape.
                        std::stringstream message;
                        message << "Output tensor " << it.first << " is expected to have "
                                << bindingInfo.second.GetShape() << "shape. "
                                << m_SingleOutputShape << " shape supplied. "
                                << CHECK_LOCATION().AsString();
                        throw armnn::Exception(message.str());
                    }
                }
            }
            else
            {
                throw armnn::Exception(fmt::format("Output tensor {0} is expected to have {1} dimensions. "
                                                   "{2} dimensions supplied. {3}",
                                                   it.first,
                                                   bindingInfo.second.GetShape().GetNumDimensions(),
                                                   NumOutputDimensions,
                                                   CHECK_LOCATION().AsString()));
            }
        }

        auto outputExpected = MakeTensor<T, NumOutputDimensions>(bindingInfo.second, it.second);
        if (std::is_same<T, uint8_t>::value)
        {
            BOOST_TEST(CompareTensors(outputExpected, outputStorage[it.first], true));
        }
        else
        {
            BOOST_TEST(CompareTensors(outputExpected, outputStorage[it.first]));
        }
    }
}

} // namespace armnnUtils
