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

#include <armnn/Descriptors.hpp>
#include <armnn/INetwork.hpp>
#include <armnn/TypesUtils.hpp>
#include <armnnDeserializer/IDeserializer.hpp>
#include <armnn/utility/IgnoreUnused.hpp>

#include <random>
#include <vector>

#include <boost/test/unit_test.hpp>


armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString);

std::string SerializeNetwork(const armnn::INetwork& network);

void CompareConstTensor(const armnn::ConstTensor& tensor1, const armnn::ConstTensor& tensor2);

class LayerVerifierBase : public armnn::IStrategy
{
public:
    LayerVerifierBase(const std::string& layerName,
                      const std::vector<armnn::TensorInfo>& inputInfos,
                      const std::vector<armnn::TensorInfo>& outputInfos);

    void ExecuteStrategy(const armnn::IConnectableLayer* layer,
                         const armnn::BaseDescriptor& descriptor,
                         const std::vector<armnn::ConstTensor>& constants,
                         const char* name,
                         const armnn::LayerBindingId id = 0) override;

protected:
    void VerifyNameAndConnections(const armnn::IConnectableLayer* layer, const char* name);

    void VerifyConstTensors(const std::string& tensorName,
                            const armnn::ConstTensor* expectedPtr,
                            const armnn::ConstTensor* actualPtr);

private:
    std::string m_LayerName;
    std::vector<armnn::TensorInfo> m_InputTensorInfos;
    std::vector<armnn::TensorInfo> m_OutputTensorInfos;
};

template<typename Descriptor>
class LayerVerifierBaseWithDescriptor : public LayerVerifierBase
{
public:
    LayerVerifierBaseWithDescriptor(const std::string& layerName,
                                    const std::vector<armnn::TensorInfo>& inputInfos,
                                    const std::vector<armnn::TensorInfo>& outputInfos,
                                    const Descriptor& descriptor)
        : LayerVerifierBase(layerName, inputInfos, outputInfos)
        , m_Descriptor(descriptor) {}

    void ExecuteStrategy(const armnn::IConnectableLayer* layer,
                         const armnn::BaseDescriptor& descriptor,
                         const std::vector<armnn::ConstTensor>& constants,
                         const char* name,
                         const armnn::LayerBindingId id = 0) override
    {
        armnn::IgnoreUnused(constants, id);
        switch (layer->GetType())
        {
            case armnn::LayerType::Input: break;
            case armnn::LayerType::Output: break;
            default:
            {
                VerifyNameAndConnections(layer, name);
                const Descriptor& internalDescriptor = static_cast<const Descriptor&>(descriptor);
                VerifyDescriptor(internalDescriptor);
                break;
            }
        }
    }

protected:
    void VerifyDescriptor(const Descriptor& descriptor)
    {
        BOOST_CHECK(descriptor == m_Descriptor);
    }

    Descriptor m_Descriptor;
};

template<typename T>
void CompareConstTensorData(const void* data1, const void* data2, unsigned int numElements)
{
    T typedData1 = static_cast<T>(data1);
    T typedData2 = static_cast<T>(data2);
    BOOST_CHECK(typedData1);
    BOOST_CHECK(typedData2);

    for (unsigned int i = 0; i < numElements; i++)
    {
        BOOST_TEST(typedData1[i] == typedData2[i]);
    }
}


template <typename Descriptor>
class LayerVerifierBaseWithDescriptorAndConstants : public LayerVerifierBaseWithDescriptor<Descriptor>
{
public:
    LayerVerifierBaseWithDescriptorAndConstants(const std::string& layerName,
                                                const std::vector<armnn::TensorInfo>& inputInfos,
                                                const std::vector<armnn::TensorInfo>& outputInfos,
                                                const Descriptor& descriptor,
                                                const std::vector<armnn::ConstTensor>& constants)
            : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
            , m_Constants(constants) {}

    void ExecuteStrategy(const armnn::IConnectableLayer* layer,
                         const armnn::BaseDescriptor& descriptor,
                         const std::vector<armnn::ConstTensor>& constants,
                         const char* name,
                         const armnn::LayerBindingId id = 0) override
    {
        armnn::IgnoreUnused(id);

        switch (layer->GetType())
        {
            case armnn::LayerType::Input: break;
            case armnn::LayerType::Output: break;
            default:
            {
                this->VerifyNameAndConnections(layer, name);
                const Descriptor& internalDescriptor = static_cast<const Descriptor&>(descriptor);
                this->VerifyDescriptor(internalDescriptor);

                for(std::size_t i = 0; i < constants.size(); i++)
                {
                    CompareConstTensor(constants[i], m_Constants[i]);
                }
            }
        }
    }

private:
    std::vector<armnn::ConstTensor> m_Constants;
};

template<typename DataType>
static std::vector<DataType> GenerateRandomData(size_t size)
{
    constexpr bool isIntegerType = std::is_integral<DataType>::value;
    using Distribution =
        typename std::conditional<isIntegerType,
                                  std::uniform_int_distribution<DataType>,
                                  std::uniform_real_distribution<DataType>>::type;

    static constexpr DataType lowerLimit = std::numeric_limits<DataType>::min();
    static constexpr DataType upperLimit = std::numeric_limits<DataType>::max();

    static Distribution distribution(lowerLimit, upperLimit);
    static std::default_random_engine generator;

    std::vector<DataType> randomData(size);
    std::generate(randomData.begin(), randomData.end(), []() { return distribution(generator); });

    return randomData;
}