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

#include "TensorFwd.hpp"

#include "Exceptions.hpp"
#include "Optional.hpp"
#include "Types.hpp"

#include <array>
#include <initializer_list>
#include <vector>

namespace armnn
{

class TensorShape
{
public:
    /// Empty (invalid) constructor.
    TensorShape();

    /// Constructor for TensorShape
    /// @param numDimensions - Tensor rank.
    /// @param initDimensionsSpecificity (optional) - value to initialize the specificity of each dimension size.
    explicit TensorShape(unsigned int numDimensions, bool initDimensionsSpecificity = true);

    /// Constructor for TensorShape
    /// @param numDimensions - Tensor rank.
    /// @param dimensionSizes - Size of each of dimension.
    TensorShape(unsigned int numDimensions, const unsigned int* dimensionSizes);

    /// Constructor for TensorShape
    /// @param dimensionSizeList - Size of each of dimension.
    TensorShape(std::initializer_list<unsigned int> dimensionSizeList);

    /// Copy Constructor for TensorShape
    /// @param other - TensorShape to copy from.
    TensorShape(const TensorShape& other);

    /// Constructor for TensorShape
    /// @param numDimensions - Tensor rank.
    /// @param dimensionSizes - Size of each of dimension.
    /// @param dimensionsSpecificity - Flags to indicate which dimension has its size specified.
    TensorShape(unsigned int numDimensions, const unsigned int* dimensionSizes, const bool* dimensionsSpecificity);

    /// Constructor for TensorShape
    /// @param dimensionSizeList - Size of each of dimension.
    /// @param dimensionsSpecificityList - Flags to indicate which dimension size is specified.
    TensorShape(std::initializer_list<unsigned int> dimensionSizeList,
                std::initializer_list<bool> dimensionsSpecificityList);

    /// Constructor for TensorShape
    /// @param dimensionality - Parameter to indicate if the Tensor is a Scalar, a Tensor of known dimensionality
    /// or a Tensor of unknown dimensionality.
    explicit TensorShape(Dimensionality dimensionality);

    /// Assignation function
    /// @param other - TensorShape to copy from.
    TensorShape& operator=(const TensorShape& other);

    /// Read only operator
    /// @param i - Dimension index.
    unsigned int operator[](unsigned int i) const;

    /// Read and write operator
    /// @param i - Dimension index.
    unsigned int& operator[](unsigned int i);

    /// Equality comparison operator
    /// @param other - TensorShape to compare with.
    bool operator==(const TensorShape& other) const;

    /// Inequality comparison operator
    /// @param other - TensorShape to compare with.
    bool operator!=(const TensorShape& other) const;

    /// Function that returns the tensor rank.
    /// @return - Tensor rank.
    unsigned int GetNumDimensions() const;

    /// Function that calculates the tensor elements by multiplying all dimension size which are Specified.
    /// @return - Total number of elements in the tensor.
    unsigned int GetNumElements() const;

    /// Function that returns the tensor type.
    /// @return - Parameter to indicate if the Tensor is a scalar, a Tensor of known dimensionality or
    /// a Tensor of unknown dimensionality
    Dimensionality GetDimensionality() const { return m_Dimensionality; }

    /// Gets information about if the dimension size has been specified or not
    /// @param i - Dimension index.
    /// @return - Flag to indicate if the dimension "i" has a specified size.
    bool GetDimensionSpecificity(unsigned int i) const;

    /// Sets the tensor rank and therefore the Dimensionality is set to Specified if it was not.
    /// @param numDimensions - Tensor rank.
    /// @param initDimensionsSpecificity (optional) - value to initialize the specificity of each dimension size.
    void SetNumDimensions(unsigned int numDimensions, bool initDimensionsSpecificity = false);

    /// Sets the size of the indicated dimension and Specificity for that dimension is set to true.
    /// @param i - Dimension index.
    /// @param dimensionSize - size of one dimension.
    void SetDimensionSize(unsigned int i, unsigned int dimensionSize);

    /// Checks if there is at least one dimension not specified. AND of all array elements.
    /// @return - True when all dimension sizes are specified. False when at least one dimension size is not specified.
    bool AreAllDimensionsSpecified() const;

    /// Checks if there is at least one dimension specified. OR of all array elements.
    /// @return - True at least one dimension sizes is specified. False when all dimension sizes are not specified.
    bool IsAtLeastOneDimensionSpecified() const;

private:
    /// Array of the dimension sizes.
    std::array<unsigned int, MaxNumOfTensorDimensions> m_Dimensions{};

    /// Array of flags to indicate if the size of each of the dimensions is specified or not
    std::array<bool, MaxNumOfTensorDimensions> m_DimensionsSpecificity = {true};

    /// Tensor rank
    unsigned int m_NumDimensions{};

    /// Tensor type: Specified, NotSpecified or Scalar.
    Dimensionality m_Dimensionality = Dimensionality::Specified;

    /// Checks if the dimension index given is within range.
    /// @param i - Dimension index.
    void CheckDimensionIndex(unsigned int i) const;

    /// Checks if the tensor rank given is within range.
    /// @param numDimensions - Tensor rank.
    static void CheckValidNumDimensions(unsigned int numDimensions) ;

    /// Checks if the size of the dimension index given is specified.
    /// @param i - Dimension index.
    void CheckDimensionSpecified(unsigned int i) const;

    /// Checks if this is a scalar.
    void CheckScalar() const;

    /// Checks if the number of dimensions is unknown, i.e. rank is unspecified.
    void CheckUnspecifiedNumDimensions() const;

    /// Checks if the number of dimensions is known, i.e. rank is specified.
    void CheckSpecifiedNumDimensions() const;
};

class TensorInfo
{
public:
    /// Empty (invalid) constructor.
    TensorInfo();

    TensorInfo(const TensorShape& shape,
               DataType dataType,
               float quantizationScale = 0.0f,
               int32_t quantizationOffset = 0);

    TensorInfo(unsigned int numDimensions,
               const unsigned int* dimensionSizes,
               DataType dataType,
               float quantizationScale = 0.0f,
               int32_t quantizationOffset = 0);

    TensorInfo(const TensorShape& shape,
               DataType dataType,
               const std::vector<float>& quantizationScales,
               unsigned int quantizationDim);

    TensorInfo(unsigned int numDimensions,
               const unsigned int* dimensionSizes,
               DataType dataType,
               const std::vector<float>& quantizationScales,
               unsigned int quantizationDim);

    TensorInfo(const TensorInfo& other);

    TensorInfo& operator=(const TensorInfo& other);

    bool operator==(const TensorInfo& other) const;
    bool operator!=(const TensorInfo& other) const;

    const TensorShape& GetShape() const              { return m_Shape; }
    TensorShape& GetShape()                          { return m_Shape; }
    void SetShape(const TensorShape& newShape)       { m_Shape = newShape; }

    unsigned int GetNumDimensions() const            { return m_Shape.GetNumDimensions(); }
    unsigned int GetNumElements() const              { return m_Shape.GetNumElements(); }

    DataType GetDataType() const                     { return m_DataType; }
    void SetDataType(DataType type)                  { m_DataType = type; }

    bool HasMultipleQuantizationScales() const       { return m_Quantization.m_Scales.size() > 1; }

    bool HasPerAxisQuantization() const;

    std::vector<float> GetQuantizationScales() const;
    void SetQuantizationScales(const std::vector<float>& scales);

    float GetQuantizationScale() const;
    void SetQuantizationScale(float scale);

    int32_t GetQuantizationOffset() const;
    void SetQuantizationOffset(int32_t offset);

    Optional<unsigned int> GetQuantizationDim() const;
    void SetQuantizationDim(const Optional<unsigned int>& quantizationDim);

    bool IsQuantized() const;

    /// Check that the types are the same and, if quantize, that the quantization parameters are the same.
    bool IsTypeSpaceMatch(const TensorInfo& other) const;

    unsigned int GetNumBytes() const;

private:
    TensorShape m_Shape;
    DataType    m_DataType;

    /// Vectors of scale and offset are used for per-axis quantization.
    struct Quantization
    {
        Quantization()
            : m_Scales{}
            , m_Offset(EmptyOptional())
            , m_QuantizationDim(EmptyOptional()) {}

        bool operator==(const Quantization& other) const
        {
            return ((m_Scales == other.m_Scales) && (m_Offset == other.m_Offset) &&
                (m_QuantizationDim == other.m_QuantizationDim));
        }

        std::vector<float>     m_Scales;
        Optional<int32_t>      m_Offset;
        Optional<unsigned int> m_QuantizationDim;

    } m_Quantization;
};

using BindingPointInfo = std::pair<armnn::LayerBindingId, armnn::TensorInfo>;

template<typename MemoryType>
class BaseTensor
{
public:
    /// Empty (invalid) constructor.
    BaseTensor();

    /// Constructor from a raw memory pointer.
    /// @param memoryArea - Region of CPU-addressable memory where tensor data will be stored. Must be valid while
    /// workloads are on the fly. Tensor instances do not claim ownership of referenced memory regions, that is,
    /// no attempt will be made by ArmNN to free these memory regions automatically.
    BaseTensor(const TensorInfo& info, MemoryType memoryArea);

    /// Tensors are copyable.
    BaseTensor(const BaseTensor& other);

    /// Tensors are copyable.
    BaseTensor& operator=(const BaseTensor&);

    const TensorInfo& GetInfo() const { return m_Info; }
    TensorInfo& GetInfo() { return m_Info; }
    const TensorShape& GetShape() const { return m_Info.GetShape(); }
    TensorShape& GetShape() { return m_Info.GetShape(); }

    DataType GetDataType() const                    { return m_Info.GetDataType(); }
    unsigned int GetNumDimensions() const { return m_Info.GetNumDimensions(); }
    unsigned int GetNumBytes() const { return m_Info.GetNumBytes(); }
    unsigned int GetNumElements() const { return m_Info.GetNumElements(); }

    MemoryType GetMemoryArea() const { return m_MemoryArea; }

protected:
    /// Protected destructor to stop users from making these
    /// (could still new one on the heap and then leak it...)
    ~BaseTensor() {}

    MemoryType m_MemoryArea;

private:
    TensorInfo m_Info;
};

/// A tensor defined by a TensorInfo (shape and data type) and a mutable backing store.
class Tensor : public BaseTensor<void*>
{
public:
    /// Brings in the constructors and assignment operator.
    using BaseTensor<void*>::BaseTensor;
};

/// A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
class ConstTensor : public BaseTensor<const void*>
{
public:
    /// Brings in the constructors and assignment operator.
    using BaseTensor<const void*>::BaseTensor;
    ConstTensor() : BaseTensor<const void*>() {} // This needs to be redefined explicitly??

    /// Can be implicitly constructed from non-const Tensor.
    ConstTensor(const Tensor& other) : BaseTensor<const void*>(other.GetInfo(), other.GetMemoryArea()) {}

    /// Constructor from a backing container.
    /// @param container - An stl-like container type which implements data() and size() methods.
    /// Presence of data() and size() is a strong indicator of the continuous memory layout of the container,
    /// which is a requirement for Tensor data. Tensor instances do not claim ownership of referenced memory regions,
    /// that is, no attempt will be made by ArmNN to free these memory regions automatically.
    template < template<typename, typename...> class ContainerType, typename T, typename...ContainerArgs >
    ConstTensor(const TensorInfo& info, const ContainerType<T, ContainerArgs...>& container)
        : BaseTensor<const void*>(info, container.data())
    {
        if (container.size() * sizeof(T) != info.GetNumBytes())
        {
            throw InvalidArgumentException("Container size is not correct");
        }
    }
};

using InputTensors = std::vector<std::pair<LayerBindingId, class ConstTensor>>;
using OutputTensors = std::vector<std::pair<LayerBindingId, class Tensor>>;

} // namespace armnn
