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

#pragma once

#include "BaseIterator.hpp"

#include <armnnUtils/FloatingPointConverter.hpp>
#include <armnnUtils/TensorUtils.hpp>

#include <armnn/utility/Assert.hpp>

namespace armnn
{

namespace
{

inline std::unique_ptr<Decoder<float>> MakeSigned32PerAxisDecoder(const TensorInfo& info, const void* data)
{
    auto params = armnnUtils::GetPerAxisParams(info);
    return std::make_unique<ScaledInt32PerAxisDecoder>(
        static_cast<const int32_t*>(data),
        params.second,
        params.first);
}

inline std::unique_ptr<Decoder<float>> MakeSigned32Decoder(const TensorInfo& info, const void* data)
{
    if(info.HasMultipleQuantizationScales())
    {
        // NOTE: If we have multiple quantization scales, we create a ScaledInt32PerAxisDecoder.
        // This will be used to decode per-axis quantized convolution biases.
        return MakeSigned32PerAxisDecoder(info, data);
    }
    else
    {
        if (info.GetQuantizationDim().has_value())
        {
            // NOTE: Even though we only have a single quantization scale, if the quantization
            // dimension is set, the tensor has per-axis quantization and we need to create a
            // ScaledInt32PerAxisDecoder
            return MakeSigned32PerAxisDecoder(info, data);
        }

        const float scale = info.GetQuantizationScale();
        if (scale == 0.f)
        {
            // NOTE:: If no quantization scale is set, we create an Int32Decoder, which simply
            // casts the int value to float. This will be used for any INT32 data other than
            // convolution biases.
            return std::make_unique<Int32Decoder>(static_cast<const int32_t*>(data));
        }

        // NOTE: If we only have a single (non-zero) quantization scale and no quantization
        // dimension is specified, we need to create a ScaledInt32Decoder. This will be used
        // to decode per-tensor quantized convolution biases.
        return std::make_unique<ScaledInt32Decoder>(static_cast<const int32_t*>(data), scale);
    }
}

} // anonymous namespace

template<typename T>
inline std::unique_ptr<Decoder<T>> MakeDecoder(const TensorInfo& info, const void* data = nullptr);

template<>
inline std::unique_ptr<Decoder<float>> MakeDecoder(const TensorInfo& info, const void* data)
{
    switch(info.GetDataType())
    {
        ARMNN_NO_DEPRECATE_WARN_BEGIN
        case armnn::DataType::QuantizedSymm8PerAxis:
        {
            std::pair<unsigned int, std::vector<float>> params = armnnUtils::GetPerAxisParams(info);
            return std::make_unique<QSymm8PerAxisDecoder>(
                static_cast<const int8_t*>(data),
                params.second,
                params.first);
        }
        ARMNN_NO_DEPRECATE_WARN_END
        case DataType::QAsymmS8:
        {
            return std::make_unique<QASymmS8Decoder>(
                static_cast<const int8_t*>(data),
                info.GetQuantizationScale(),
                info.GetQuantizationOffset());
        }
        case DataType::QAsymmU8:
        {
            return std::make_unique<QASymm8Decoder>(
                static_cast<const uint8_t*>(data),
                info.GetQuantizationScale(),
                info.GetQuantizationOffset());
        }
        case DataType::QSymmS16:
        {
            return std::make_unique<QSymm16Decoder>(
                static_cast<const int16_t*>(data),
                info.GetQuantizationScale(),
                info.GetQuantizationOffset());
        }
        case DataType::BFloat16:
        {
            return std::make_unique<BFloat16Decoder>(static_cast<const BFloat16*>(data));
        }
        case DataType::Float16:
        {
            return std::make_unique<Float16Decoder>(static_cast<const Half*>(data));
        }
        case DataType::Float32:
        {
            return std::make_unique<Float32Decoder>(static_cast<const float*>(data));
        }
        case DataType::Signed32:
        {
            return MakeSigned32Decoder(info, data);
        }
        case DataType::QSymmS8:
        {
            if (info.HasPerAxisQuantization())
            {
                std::pair<unsigned int, std::vector<float>> params = armnnUtils::GetPerAxisParams(info);
                return std::make_unique<QSymm8PerAxisDecoder>(
                    static_cast<const int8_t*>(data),
                    params.second,
                    params.first);
            }
            else
            {
                return std::make_unique<QSymmS8Decoder>(
                    static_cast<const int8_t*>(data),
                    info.GetQuantizationScale(),
                    info.GetQuantizationOffset());
            }
        }
        case armnn::DataType::Boolean:
        {
            return std::make_unique<BooleanDecoder>(static_cast<const uint8_t*>(data));
        }
        default:
        {
            ARMNN_ASSERT_MSG(false, "Unsupported Data Type!");
            break;
        }
    }
    return nullptr;
}

template<>
inline std::unique_ptr<Decoder<int32_t>> MakeDecoder(const TensorInfo& info, const void* data)
{
    switch(info.GetDataType())
    {
        case DataType::Signed32:
        {
            return std::make_unique<Int32ToInt32tDecoder>(static_cast<const int32_t*>(data));
        }
        default:
        {
            ARMNN_ASSERT_MSG(false, "Unsupported Data Type!");
            break;
        }
    }
    return nullptr;
}

} //namespace armnn
