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

#pragma once

#include "SchemaSerialize.hpp"

#include <armnn/IRuntime.hpp>
#include <armnnDeserializer/IDeserializer.hpp>

#include <boost/core/ignore_unused.hpp>
#include <boost/assert.hpp>
#include <boost/format.hpp>

#include <ResolveType.hpp>
#include "test/TensorHelpers.hpp"

#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"

#include <ArmnnSchema_generated.h>

using armnnDeserializer::IDeserializer;
using TensorRawPtr = armnnSerializer::TensorInfo*;

struct ParserFlatbuffersSerializeFixture
{
    ParserFlatbuffersSerializeFixture() :
        m_Parser(IDeserializer::Create()),
        m_Runtime(armnn::IRuntime::Create(armnn::IRuntime::CreationOptions())),
        m_NetworkIdentifier(-1)
    {
    }

    std::vector<uint8_t> m_GraphBinary;
    std::string m_JsonString;
    std::unique_ptr<IDeserializer, void (*)(IDeserializer* 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;

    void Setup()
    {
        bool ok = ReadStringToBinary();
        if (!ok)
        {
            throw armnn::Exception("LoadNetwork failed while reading binary input");
        }

        armnn::INetworkPtr network =
                m_Parser->CreateNetworkFromBinary(m_GraphBinary);

        if (!network)
        {
            throw armnn::Exception("The parser failed to create an ArmNN network");
        }

        auto optimized = Optimize(*network, {armnn::Compute::CpuRef},
                                  m_Runtime->GetDeviceSpec());

        std::string errorMessage;
        armnn::Status ret = m_Runtime->LoadNetwork(m_NetworkIdentifier, move(optimized), errorMessage);

        if (ret != armnn::Status::Success)
        {
            throw armnn::Exception(
                    boost::str(
                            boost::format("The runtime failed to load the network. "
                                          "Error was: %1%. in %2% [%3%:%4%]") %
                            errorMessage %
                            __func__ %
                            __FILE__ %
                            __LINE__));
        }

    }

    void SetupSingleInputSingleOutput(const std::string& inputName, const std::string& outputName)
    {
        // Store 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();
    }

    bool ReadStringToBinary()
    {
        std::string schemafile(&deserialize_schema_start, &deserialize_schema_end);

        // parse schema first, so we can use it to parse the data after
        flatbuffers::Parser parser;

        bool ok = parser.Parse(schemafile.c_str());
        BOOST_ASSERT_MSG(ok, "Failed to parse schema file");

        ok &= parser.Parse(m_JsonString.c_str());
        BOOST_ASSERT_MSG(ok, "Failed to parse json input");

        if (!ok)
        {
            return false;
        }

        {
            const uint8_t* bufferPtr = parser.builder_.GetBufferPointer();
            size_t size = static_cast<size_t>(parser.builder_.GetSize());
            m_GraphBinary.assign(bufferPtr, bufferPtr+size);
        }
        return ok;
    }

    /// Executes the network with the given input tensor and checks the result against the given output tensor.
    /// This overload assumes the network has a single input and a single output.
    template<std::size_t NumOutputDimensions,
             armnn::DataType ArmnnType,
             typename DataType = armnn::ResolveType<ArmnnType>>
    void RunTest(unsigned int layersId,
                 const std::vector<DataType>& inputData,
                 const std::vector<DataType>& expectedOutputData);

    template<std::size_t NumOutputDimensions,
             armnn::DataType ArmnnInputType,
             armnn::DataType ArmnnOutputType,
             typename InputDataType = armnn::ResolveType<ArmnnInputType>,
             typename OutputDataType = armnn::ResolveType<ArmnnOutputType>>
    void RunTest(unsigned int layersId,
                 const std::vector<InputDataType>& inputData,
                 const std::vector<OutputDataType>& 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,
             armnn::DataType ArmnnType,
             typename DataType = armnn::ResolveType<ArmnnType>>
    void RunTest(unsigned int layersId,
                 const std::map<std::string, std::vector<DataType>>& inputData,
                 const std::map<std::string, std::vector<DataType>>& expectedOutputData);

    template<std::size_t NumOutputDimensions,
             armnn::DataType ArmnnInputType,
             armnn::DataType ArmnnOutputType,
             typename InputDataType = armnn::ResolveType<ArmnnInputType>,
             typename OutputDataType = armnn::ResolveType<ArmnnOutputType>>
    void RunTest(unsigned int layersId,
                 const std::map<std::string, std::vector<InputDataType>>& inputData,
                 const std::map<std::string, std::vector<OutputDataType>>& expectedOutputData);

    void CheckTensors(const TensorRawPtr& tensors, size_t shapeSize, const std::vector<int32_t>& shape,
                      armnnSerializer::TensorInfo tensorType, const std::string& name,
                      const float scale, const int64_t zeroPoint)
    {
        boost::ignore_unused(name);
        BOOST_CHECK_EQUAL(shapeSize, tensors->dimensions()->size());
        BOOST_CHECK_EQUAL_COLLECTIONS(shape.begin(), shape.end(),
                                      tensors->dimensions()->begin(), tensors->dimensions()->end());
        BOOST_CHECK_EQUAL(tensorType.dataType(), tensors->dataType());
        BOOST_CHECK_EQUAL(scale, tensors->quantizationScale());
        BOOST_CHECK_EQUAL(zeroPoint, tensors->quantizationOffset());
    }
};

template<std::size_t NumOutputDimensions, armnn::DataType ArmnnType, typename DataType>
void ParserFlatbuffersSerializeFixture::RunTest(unsigned int layersId,
                                                const std::vector<DataType>& inputData,
                                                const std::vector<DataType>& expectedOutputData)
{
    RunTest<NumOutputDimensions, ArmnnType, ArmnnType, DataType, DataType>(layersId, inputData, expectedOutputData);
}

template<std::size_t NumOutputDimensions,
         armnn::DataType ArmnnInputType,
         armnn::DataType ArmnnOutputType,
         typename InputDataType,
         typename OutputDataType>
void ParserFlatbuffersSerializeFixture::RunTest(unsigned int layersId,
                                                const std::vector<InputDataType>& inputData,
                                                const std::vector<OutputDataType>& expectedOutputData)
{
    RunTest<NumOutputDimensions, ArmnnInputType, ArmnnOutputType>(layersId,
                                                                  { { m_SingleInputName, inputData } },
                                                                  { { m_SingleOutputName, expectedOutputData } });
}

template<std::size_t NumOutputDimensions, armnn::DataType ArmnnType, typename DataType>
void ParserFlatbuffersSerializeFixture::RunTest(unsigned int layersId,
                                                const std::map<std::string, std::vector<DataType>>& inputData,
                                                const std::map<std::string, std::vector<DataType>>& expectedOutputData)
{
    RunTest<NumOutputDimensions, ArmnnType, ArmnnType, DataType, DataType>(layersId, inputData, expectedOutputData);
}

template<std::size_t NumOutputDimensions,
         armnn::DataType ArmnnInputType,
         armnn::DataType ArmnnOutputType,
         typename InputDataType,
         typename OutputDataType>
void ParserFlatbuffersSerializeFixture::RunTest(
    unsigned int layersId,
    const std::map<std::string, std::vector<InputDataType>>& inputData,
    const std::map<std::string, std::vector<OutputDataType>>& expectedOutputData)
{
    auto ConvertBindingInfo = [](const armnnDeserializer::BindingPointInfo& bindingInfo)
        {
            return std::make_pair(bindingInfo.m_BindingId, bindingInfo.m_TensorInfo);
        };

    // Setup the armnn input tensors from the given vectors.
    armnn::InputTensors inputTensors;
    for (auto&& it : inputData)
    {
        armnn::BindingPointInfo bindingInfo = ConvertBindingInfo(
            m_Parser->GetNetworkInputBindingInfo(layersId, it.first));
        armnn::VerifyTensorInfoDataType(bindingInfo.second, ArmnnInputType);
        inputTensors.push_back({ bindingInfo.first, armnn::ConstTensor(bindingInfo.second, it.second.data()) });
    }

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

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

    // Compare each output tensor to the expected values
    for (auto&& it : expectedOutputData)
    {
        armnn::BindingPointInfo bindingInfo = ConvertBindingInfo(
            m_Parser->GetNetworkOutputBindingInfo(layersId, it.first));
        auto outputExpected = MakeTensor<OutputDataType, NumOutputDimensions>(bindingInfo.second, it.second);
        BOOST_TEST(CompareTensors(outputExpected, outputStorage[it.first]));
    }
}
