//
// Copyright © 2017 Arm Ltd. All rights reserved.
// See LICENSE file in the project root for full license information.
//
#pragma once

#include <armnn/Exceptions.hpp>
#include <VerificationHelpers.hpp>

#include <array>
#include <cstdint>
#include <vector>
#include <utility>

class InferenceTestImageException : public armnn::Exception
{
public:
    using Exception::Exception;
};

class InferenceTestImageLoadFailed : public InferenceTestImageException
{
public:
    using InferenceTestImageException::InferenceTestImageException;
};

class InferenceTestImageOutOfBoundsAccess : public InferenceTestImageException
{
public:
    using InferenceTestImageException::InferenceTestImageException;
};

class InferenceTestImageResizeFailed : public InferenceTestImageException
{
public:
    using InferenceTestImageException::InferenceTestImageException;
};

class InferenceTestImageWriteFailed : public InferenceTestImageException
{
public:
    using InferenceTestImageException::InferenceTestImageException;
};

class UnknownImageChannelLayout : public InferenceTestImageException
{
public:
    using InferenceTestImageException::InferenceTestImageException;
};

class InferenceTestImage
{
public:
    enum class WriteFormat
    {
        Png,
        Bmp,
        Tga
    };

    // Common names used to identify a channel in a pixel.
    enum class ResizingMethods
    {
        STB,
        BilinearAndNormalized,
    };

    explicit InferenceTestImage(const char* filePath);

    InferenceTestImage(InferenceTestImage&&) = delete;
    InferenceTestImage(const InferenceTestImage&) = delete;
    InferenceTestImage& operator=(const InferenceTestImage&) = delete;
    InferenceTestImage& operator=(InferenceTestImage&&) = delete;

    unsigned int GetWidth() const { return m_Width; }
    unsigned int GetHeight() const { return m_Height; }
    unsigned int GetNumChannels() const { return m_NumChannels; }
    unsigned int GetNumElements() const { return GetWidth() * GetHeight() * GetNumChannels(); }
    unsigned int GetSizeInBytes() const { return GetNumElements() * GetSingleElementSizeInBytes(); }

    // Returns the pixel identified by the given coordinates as a 3-channel value.
    // Channels beyond the third are dropped. If the image provides less than 3 channels, the non-existent
    // channels of the pixel will be filled with 0. Channels are returned in RGB order (that is, the first element
    // of the tuple corresponds to the Red channel, whereas the last element is the Blue channel).
    std::tuple<uint8_t, uint8_t, uint8_t> GetPixelAs3Channels(unsigned int x, unsigned int y) const;

    void StbResize(InferenceTestImage& im, const unsigned int newWidth, const unsigned int newHeight);


    std::vector<float> Resize(unsigned int newWidth,
                              unsigned int newHeight,
                              const armnn::CheckLocation& location,
                              const ResizingMethods meth = ResizingMethods::STB,
                              const std::array<float, 3>& mean = {{0.0, 0.0, 0.0}},
                              const std::array<float, 3>& stddev = {{1.0, 1.0, 1.0}});

    void Write(WriteFormat format, const char* filePath) const;

private:
    static unsigned int GetSingleElementSizeInBytes()
    {
        return sizeof(decltype(std::declval<InferenceTestImage>().m_Data[0]));
    }

    std::vector<uint8_t> m_Data;
    unsigned int m_Width;
    unsigned int m_Height;
    unsigned int m_NumChannels;
};

// Common names used to identify a channel in a pixel.
enum class ImageChannel
{
    R,
    G,
    B
};

// Channel layouts handled by the test framework.
enum class ImageChannelLayout
{
    Rgb,
    Bgr
};

// Reads the contents of an inference test image as 3-channel pixels whose channel values have been normalized (scaled)
// and now lie in the range [0,1]. Channel data is stored according to the ArmNN layout (CHW). The order in which
// channels appear in the resulting vector is defined by the provided layout.
std::vector<float> GetImageDataInArmNnLayoutAsNormalizedFloats(ImageChannelLayout layout,
    const InferenceTestImage& image);

// Reads the contents of an inference test image as 3-channel pixels, whose value is the result of subtracting the mean
// from the values in the original image. Channel data is stored according to the ArmNN layout (CHW). The order in
// which channels appear in the resulting vector is defined by the provided layout. The order of the channels of the
// provided mean should also match the given layout.
std::vector<float> GetImageDataInArmNnLayoutAsFloatsSubtractingMean(ImageChannelLayout layout,
    const InferenceTestImage& image,
    const std::array<float, 3>& mean);

// Reads the contents of an inference test image as 3-channel pixels and returns the image data as normalized float
// values. The returned image stay in the original order (HWC) order. The C order may be changed according to the
// supplied layout value.
std::vector<float> GetImageDataAsNormalizedFloats(ImageChannelLayout layout,
                                                  const InferenceTestImage& image);
