//
// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once

#include <armnn/Tensor.hpp>
#include <armnn/DescriptorsFwd.hpp>

#include <armnn/utility/NumericCast.hpp>

#include <arm_compute/core/ITensor.h>
#include <arm_compute/core/TensorInfo.h>
#include <arm_compute/core/Types.h>

#include <Half.hpp>

namespace armnn
{
class ITensorHandle;

namespace armcomputetensorutils
{

/// Utility function to map an armnn::DataType to corresponding arm_compute::DataType.
arm_compute::DataType GetArmComputeDataType(armnn::DataType dataType, bool multiScales);

/// Utility function to map an arm_compute::DataType to corresponding armnn::DataType.
armnn::DataType GetArmNNDataType(arm_compute::DataType datatype);

/// Utility function used to set up an arm_compute::Coordinates from a vector of ArmNN Axes for reduction functions
arm_compute::Coordinates BuildArmComputeReductionCoordinates(size_t inputDimensions,
                                                             unsigned int originalInputRank,
                                                             const std::vector<unsigned int>& armnnAxes);

/// Utility function used to setup an arm_compute::TensorShape object from an armnn::TensorShape.
arm_compute::TensorShape BuildArmComputeTensorShape(const armnn::TensorShape& tensorShape);

/// Utility function used to setup an arm_compute::ITensorInfo object whose dimensions are based on the given
/// armnn::ITensorInfo.
arm_compute::TensorInfo BuildArmComputeTensorInfo(const armnn::TensorInfo& tensorInfo);

/// Utility function used to setup an arm_compute::ITensorInfo object whose dimensions are based on the given
/// armnn::ITensorInfo.
/// armnn::DataLayout.
arm_compute::TensorInfo BuildArmComputeTensorInfo(const armnn::TensorInfo& tensorInfo,
                                                  armnn::DataLayout dataLayout);

/// Utility function used to convert armnn::DataLayout to arm_compute::DataLayout
/// armnn::DataLayout.
arm_compute::DataLayout ConvertDataLayout(armnn::DataLayout dataLayout);

/// Utility function used to setup an arm_compute::PoolingLayerInfo object from given
/// armnn::Pooling2dDescriptor
/// bool fpMixedPrecision
arm_compute::PoolingLayerInfo BuildArmComputePoolingLayerInfo(const Pooling2dDescriptor& descriptor,
                                                              bool fpMixedPrecision = false);

/// Utility function used to setup an arm_compute::Pooling3dLayerInfo object from given
/// armnn::Pooling3dDescriptor
/// bool fpMixedPrecision
arm_compute::Pooling3dLayerInfo BuildArmComputePooling3dLayerInfo(const Pooling3dDescriptor& descriptor,
                                                                  bool fpMixedPrecision = false);

/// Utility function to setup an arm_compute::NormalizationLayerInfo object from an armnn::NormalizationDescriptor.
arm_compute::NormalizationLayerInfo BuildArmComputeNormalizationLayerInfo(const NormalizationDescriptor& desc);

/// Utility function used to setup an arm_compute::PermutationVector object from an armnn::PermutationVector.
arm_compute::PermutationVector BuildArmComputePermutationVector(const armnn::PermutationVector& vector);

/// Utility function used to setup an arm_compute::PermutationVector object from an armnn::PermutationVector.
arm_compute::PermutationVector BuildArmComputeTransposeVector(const armnn::PermutationVector& vector);

/// Utility function used to setup an arm_compute::Size2D object from width and height values.
arm_compute::Size2D BuildArmComputeSize2D(const unsigned int width, const unsigned int height);

/// Gets the appropriate PixelValue for the TensorInfo DataType
arm_compute::PixelValue GetPixelValue(const arm_compute::ITensorInfo* tensorInfo, float value);

/// Computes the depth multiplier parameter for the Depthwise Conv2d ACL workload.
unsigned int ComputeDepthwiseConv2dDepthMultiplier(armnn::DataLayout layout,
                                                   const arm_compute::TensorShape& weightsShape,
                                                   const arm_compute::TensorShape& inputShape);

/// Utility function used to setup an arm_compute::PadStrideInfo object from an armnn layer descriptor.
template <typename Descriptor>
arm_compute::PadStrideInfo BuildArmComputePadStrideInfo(const Descriptor &descriptor)
{
    return arm_compute::PadStrideInfo(descriptor.m_StrideX,
                                      descriptor.m_StrideY,
                                      descriptor.m_PadLeft,
                                      descriptor.m_PadRight,
                                      descriptor.m_PadTop,
                                      descriptor.m_PadBottom,
                                      arm_compute::DimensionRoundingType::FLOOR);
}

/// Sets up the given ArmCompute tensor's dimensions based on the given ArmNN tensor.
template <typename Tensor>
void BuildArmComputeTensor(Tensor& tensor, const armnn::TensorInfo& tensorInfo)
{
    tensor.allocator()->init(BuildArmComputeTensorInfo(tensorInfo));
}

/// Sets up the given ArmCompute tensor's dimensions based on the given ArmNN tensor.
template <typename Tensor>
void BuildArmComputeTensor(Tensor& tensor, const armnn::TensorInfo& tensorInfo, DataLayout dataLayout)
{
    tensor.allocator()->init(BuildArmComputeTensorInfo(tensorInfo, dataLayout));
}

template <typename Tensor>
void InitialiseArmComputeTensorEmpty(Tensor& tensor)
{
    tensor.allocator()->allocate();
}

/// Utility function to free unused tensors after a workload is configured and prepared
template <typename Tensor>
void FreeTensorIfUnused(std::unique_ptr<Tensor>& tensor)
{
    if (tensor && !tensor->is_used())
    {
        tensor.reset(nullptr);
    }
}

// Helper function to obtain byte offset into tensor data
inline size_t GetTensorOffset(const arm_compute::ITensorInfo& info,
                              uint32_t depthIndex,
                              uint32_t batchIndex,
                              uint32_t channelIndex,
                              uint32_t y,
                              uint32_t x)
{
    arm_compute::Coordinates coords;
    coords.set(4, static_cast<int>(depthIndex));
    coords.set(3, static_cast<int>(batchIndex));
    coords.set(2, static_cast<int>(channelIndex));
    coords.set(1, static_cast<int>(y));
    coords.set(0, static_cast<int>(x));
    return armnn::numeric_cast<size_t>(info.offset_element_in_bytes(coords));
}

// Helper function to obtain element offset into data buffer representing tensor data (assuming no strides).
inline size_t GetLinearBufferOffset(const arm_compute::ITensorInfo& info,
                                    uint32_t depthIndex,
                                    uint32_t batchIndex,
                                    uint32_t channelIndex,
                                    uint32_t y,
                                    uint32_t x)
{
    const arm_compute::TensorShape& shape = info.tensor_shape();
    uint32_t width = static_cast<uint32_t>(shape[0]);
    uint32_t height = static_cast<uint32_t>(shape[1]);
    uint32_t numChannels = static_cast<uint32_t>(shape[2]);
    uint32_t numBatches = static_cast<uint32_t>(shape[3]);
    return (((depthIndex * numBatches + batchIndex) * numChannels + channelIndex) * height + y) * width + x;
}

template <typename T>
void CopyArmComputeITensorData(const arm_compute::ITensor& srcTensor, T* dstData)
{
    // If MaxNumOfTensorDimensions is increased, this loop will need fixing.
    static_assert(MaxNumOfTensorDimensions == 5, "Please update CopyArmComputeITensorData");
    {
        const arm_compute::ITensorInfo& info = *srcTensor.info();
        const arm_compute::TensorShape& shape = info.tensor_shape();
        const uint8_t* const bufferPtr = srcTensor.buffer();
        uint32_t width = static_cast<uint32_t>(shape[0]);
        uint32_t height = static_cast<uint32_t>(shape[1]);
        uint32_t numChannels = static_cast<uint32_t>(shape[2]);
        uint32_t numBatches = static_cast<uint32_t>(shape[3]);
        uint32_t depth = static_cast<uint32_t>(shape[4]);

        for (unsigned int depthIndex = 0; depthIndex < depth; ++depthIndex)
        {
            for (unsigned int batchIndex = 0; batchIndex < numBatches; ++batchIndex)
            {
                for (unsigned int channelIndex = 0; channelIndex < numChannels; ++channelIndex)
                {
                    for (unsigned int y = 0; y < height; ++y)
                    {
                        // Copies one row from arm_compute tensor buffer to linear memory buffer.
                        // A row is the largest contiguous region we can copy, as the tensor data may be using strides.
                        memcpy(
                         dstData + GetLinearBufferOffset(info, depthIndex, batchIndex, channelIndex, y, 0),
                         bufferPtr + GetTensorOffset(info, depthIndex, batchIndex, channelIndex, y, 0),
                         width * sizeof(T));
                    }
                }
            }
        }
    }
}

template <typename T>
void CopyArmComputeITensorData(const T* srcData, arm_compute::ITensor& dstTensor)
{
    // If MaxNumOfTensorDimensions is increased, this loop will need fixing.
    static_assert(MaxNumOfTensorDimensions == 5, "Please update CopyArmComputeITensorData");
    {
        const arm_compute::ITensorInfo& info = *dstTensor.info();
        const arm_compute::TensorShape& shape = info.tensor_shape();
        uint8_t* const bufferPtr = dstTensor.buffer();
        uint32_t width = static_cast<uint32_t>(shape[0]);
        uint32_t height = static_cast<uint32_t>(shape[1]);
        uint32_t numChannels = static_cast<uint32_t>(shape[2]);
        uint32_t numBatches = static_cast<uint32_t>(shape[3]);
        uint32_t depth = static_cast<uint32_t>(shape[4]);

        for (unsigned int depthIndex = 0; depthIndex < depth; ++depthIndex)
        {
            for (unsigned int batchIndex = 0; batchIndex < numBatches; ++batchIndex)
            {
                for (unsigned int channelIndex = 0; channelIndex < numChannels; ++channelIndex)
                {
                    for (unsigned int y = 0; y < height; ++y)
                    {
                        // Copies one row from linear memory buffer to arm_compute tensor buffer.
                        // A row is the largest contiguous region we can copy, as the tensor data may be using strides.
                        memcpy(
                         bufferPtr + GetTensorOffset(info, depthIndex, batchIndex, channelIndex, y, 0),
                         srcData + GetLinearBufferOffset(info, depthIndex, batchIndex, channelIndex, y, 0),
                         width * sizeof(T));
                    }
                }
            }
        }
    }
}

/// Construct a TensorShape object from an ArmCompute object based on arm_compute::Dimensions.
/// \tparam ArmComputeType Any type that implements the Dimensions interface
/// \tparam T Shape value type
/// \param shapelike An ArmCompute object that implements the Dimensions interface
/// \param initial A default value to initialise the shape with
/// \return A TensorShape object filled from the Acl shapelike object.
template<typename ArmComputeType, typename T>
TensorShape GetTensorShape(const ArmComputeType& shapelike, T initial)
{
    std::vector<unsigned int> s(MaxNumOfTensorDimensions, initial);
    for (unsigned int i=0; i < shapelike.num_dimensions(); ++i)
    {
        s[(shapelike.num_dimensions()-1)-i] = armnn::numeric_cast<unsigned int>(shapelike[i]);
    }
    return TensorShape(armnn::numeric_cast<unsigned int>(shapelike.num_dimensions()), s.data());
};

/// Get the strides from an ACL strides object
inline TensorShape GetStrides(const arm_compute::Strides& strides)
{
    return GetTensorShape(strides, 0U);
}

/// Get the shape from an ACL shape object
inline TensorShape GetShape(const arm_compute::TensorShape& shape)
{
    return GetTensorShape(shape, 1U);
}

} // namespace armcomputetensorutils
} // namespace armnn
