/*
 * Copyright (c) 2017 ARM Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "Validation.h"

#include "arm_compute/core/Coordinates.h"
#include "arm_compute/core/Error.h"
#include "arm_compute/core/FixedPoint.h"
#include "arm_compute/core/IArray.h"
#include "arm_compute/core/TensorShape.h"
#include "arm_compute/runtime/Tensor.h"
#include "tests/IAccessor.h"
#include "tests/RawTensor.h"
#include "tests/TypePrinter.h"
#include "tests/Utils.h"
#include "tests/validation_old/half.h"

#include <array>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <iomanip>
#include <vector>

namespace arm_compute
{
namespace test
{
namespace validation
{
namespace
{
/** Get the data from *ptr after casting according to @p data_type and then convert the data to double.
 *
 * @param[in] ptr       Pointer to value.
 * @param[in] data_type Data type of both values.
 *
 * @return The data from the ptr after converted to double.
 */
double get_double_data(const void *ptr, DataType data_type)
{
    if(ptr == nullptr)
    {
        ARM_COMPUTE_ERROR("Can't dereference a null pointer!");
    }

    switch(data_type)
    {
        case DataType::U8:
            return *reinterpret_cast<const uint8_t *>(ptr);
        case DataType::S8:
            return *reinterpret_cast<const int8_t *>(ptr);
        case DataType::QS8:
            return *reinterpret_cast<const qint8_t *>(ptr);
        case DataType::U16:
            return *reinterpret_cast<const uint16_t *>(ptr);
        case DataType::S16:
            return *reinterpret_cast<const int16_t *>(ptr);
        case DataType::QS16:
            return *reinterpret_cast<const qint16_t *>(ptr);
        case DataType::U32:
            return *reinterpret_cast<const uint32_t *>(ptr);
        case DataType::S32:
            return *reinterpret_cast<const int32_t *>(ptr);
        case DataType::U64:
            return *reinterpret_cast<const uint64_t *>(ptr);
        case DataType::S64:
            return *reinterpret_cast<const int64_t *>(ptr);
        case DataType::F16:
            return *reinterpret_cast<const half_float::half *>(ptr);
        case DataType::F32:
            return *reinterpret_cast<const float *>(ptr);
        case DataType::F64:
            return *reinterpret_cast<const double *>(ptr);
        case DataType::SIZET:
            return *reinterpret_cast<const size_t *>(ptr);
        default:
            ARM_COMPUTE_ERROR("NOT SUPPORTED!");
    }
}

bool is_equal(double target, double ref, double max_absolute_error = std::numeric_limits<double>::epsilon(), double max_relative_error = 0.0001f)
{
    if(!std::isfinite(target) || !std::isfinite(ref))
    {
        return false;
    }

    // No need further check if they are equal
    if(ref == target)
    {
        return true;
    }

    // Need this check for the situation when the two values close to zero but have different sign
    if(std::abs(std::abs(ref) - std::abs(target)) <= max_absolute_error)
    {
        return true;
    }

    double relative_error = 0;

    if(std::abs(target) > std::abs(ref))
    {
        relative_error = std::abs((target - ref) / target);
    }
    else
    {
        relative_error = std::abs((ref - target) / ref);
    }

    return relative_error <= max_relative_error;
}

void check_border_element(const IAccessor &tensor, const Coordinates &id,
                          const BorderMode &border_mode, const void *border_value,
                          int64_t &num_elements, int64_t &num_mismatches)
{
    const size_t channel_size = element_size_from_data_type(tensor.data_type());
    const auto   ptr          = static_cast<const uint8_t *>(tensor(id));

    if(border_mode == BorderMode::REPLICATE)
    {
        Coordinates border_id{ id };
        border_id.set(1, 0);
        border_value = tensor(border_id);
    }

    // Iterate over all channels within one element
    for(int channel = 0; channel < tensor.num_channels(); ++channel)
    {
        const size_t channel_offset = channel * channel_size;
        const double target         = get_double_data(ptr + channel_offset, tensor.data_type());
        const double ref            = get_double_data(static_cast<const uint8_t *>(border_value) + channel_offset, tensor.data_type());
        const bool   equal          = is_equal(target, ref);

        BOOST_TEST_INFO("id = " << id);
        BOOST_TEST_INFO("channel = " << channel);
        BOOST_TEST_INFO("reference = " << std::setprecision(5) << ref);
        BOOST_TEST_INFO("target = " << std::setprecision(5) << target);
        BOOST_TEST_WARN(equal);

        if(!equal)
        {
            ++num_mismatches;
        }

        ++num_elements;
    }
}

void check_single_element(const Coordinates &id, const IAccessor &tensor, const RawTensor &reference, float tolerance_value,
                          uint64_t wrap_range, int min_channels, size_t channel_size, int64_t &num_mismatches, int64_t &num_elements)
{
    const auto ptr     = static_cast<const uint8_t *>(tensor(id));
    const auto ref_ptr = static_cast<const uint8_t *>(reference(id));

    // Iterate over all channels within one element
    for(int channel = 0; channel < min_channels; ++channel)
    {
        const size_t channel_offset = channel * channel_size;
        const double target         = get_double_data(ptr + channel_offset, reference.data_type());
        const double ref            = get_double_data(ref_ptr + channel_offset, reference.data_type());
        bool         equal          = is_equal(target, ref, tolerance_value);

        if(wrap_range != 0 && !equal)
        {
            equal = is_equal(target, ref, wrap_range - tolerance_value);
        }

        if(!equal)
        {
            BOOST_TEST_INFO("id = " << id);
            BOOST_TEST_INFO("channel = " << channel);
            BOOST_TEST_INFO("reference = " << std::setprecision(5) << ref);
            BOOST_TEST_INFO("target = " << std::setprecision(5) << target);
            BOOST_TEST_WARN(equal);
            ++num_mismatches;
        }
        ++num_elements;
    }
}
} // namespace

void validate(const arm_compute::ValidRegion &region, const arm_compute::ValidRegion &reference)
{
    BOOST_TEST(region.anchor.num_dimensions() == reference.anchor.num_dimensions());
    BOOST_TEST(region.shape.num_dimensions() == reference.shape.num_dimensions());

    for(unsigned int d = 0; d < region.anchor.num_dimensions(); ++d)
    {
        BOOST_TEST(region.anchor[d] == reference.anchor[d]);
    }

    for(unsigned int d = 0; d < region.shape.num_dimensions(); ++d)
    {
        BOOST_TEST(region.shape[d] == reference.shape[d]);
    }
}

void validate(const arm_compute::PaddingSize &padding, const arm_compute::PaddingSize &reference)
{
    BOOST_TEST(padding.top == reference.top);
    BOOST_TEST(padding.right == reference.right);
    BOOST_TEST(padding.bottom == reference.bottom);
    BOOST_TEST(padding.left == reference.left);
}

void validate(const IAccessor &tensor, const RawTensor &reference, float tolerance_value, float tolerance_number, uint64_t wrap_range)
{
    // Validate with valid region covering the entire shape
    validate(tensor, reference, shape_to_valid_region(tensor.shape()), tolerance_value, tolerance_number, wrap_range);
}

void validate(const IAccessor &tensor, const RawTensor &reference, const ValidRegion &valid_region, float tolerance_value, float tolerance_number, uint64_t wrap_range)
{
    int64_t num_mismatches = 0;
    int64_t num_elements   = 0;

    BOOST_TEST(tensor.element_size() == reference.element_size());
    BOOST_TEST(tensor.format() == reference.format());
    BOOST_TEST(tensor.data_type() == reference.data_type());
    BOOST_TEST(tensor.num_channels() == reference.num_channels());
    BOOST_TEST(compare_dimensions(tensor.shape(), reference.shape()));

    const int    min_elements = std::min(tensor.num_elements(), reference.num_elements());
    const int    min_channels = std::min(tensor.num_channels(), reference.num_channels());
    const size_t channel_size = element_size_from_data_type(reference.data_type());

    // Iterate over all elements within valid region, e.g. U8, S16, RGB888, ...
    for(int element_idx = 0; element_idx < min_elements; ++element_idx)
    {
        const Coordinates id = index2coord(reference.shape(), element_idx);
        if(is_in_valid_region(valid_region, id))
        {
            check_single_element(id, tensor, reference, tolerance_value, wrap_range, min_channels, channel_size, num_mismatches, num_elements);
        }
    }

    const int64_t absolute_tolerance_number = tolerance_number * num_elements;
    const float   percent_mismatches        = static_cast<float>(num_mismatches) / num_elements * 100.f;

    BOOST_TEST(num_mismatches <= absolute_tolerance_number,
               num_mismatches << " values (" << std::setprecision(2) << percent_mismatches
               << "%) mismatched (maximum tolerated " << std::setprecision(2) << tolerance_number << "%)");
}

void validate(const IAccessor &tensor, const RawTensor &reference, const RawTensor &valid_mask, float tolerance_value, float tolerance_number, uint64_t wrap_range)
{
    int64_t num_mismatches = 0;
    int64_t num_elements   = 0;

    BOOST_TEST(tensor.element_size() == reference.element_size());
    BOOST_TEST(tensor.format() == reference.format());
    BOOST_TEST(tensor.data_type() == reference.data_type());
    BOOST_TEST(tensor.num_channels() == reference.num_channels());
    BOOST_TEST(compare_dimensions(tensor.shape(), reference.shape()));

    const int    min_elements = std::min(tensor.num_elements(), reference.num_elements());
    const int    min_channels = std::min(tensor.num_channels(), reference.num_channels());
    const size_t channel_size = element_size_from_data_type(reference.data_type());

    // Iterate over all elements within valid region, e.g. U8, S16, RGB888, ...
    for(int element_idx = 0; element_idx < min_elements; ++element_idx)
    {
        const Coordinates id = index2coord(reference.shape(), element_idx);
        if(valid_mask[element_idx] == 1)
        {
            check_single_element(id, tensor, reference, tolerance_value, wrap_range, min_channels, channel_size, num_mismatches, num_elements);
        }
        else
        {
            ++num_elements;
        }
    }

    const int64_t absolute_tolerance_number = tolerance_number * num_elements;
    const float   percent_mismatches        = static_cast<float>(num_mismatches) / num_elements * 100.f;

    BOOST_TEST(num_mismatches <= absolute_tolerance_number,
               num_mismatches << " values (" << std::setprecision(2) << percent_mismatches
               << "%) mismatched (maximum tolerated " << std::setprecision(2) << tolerance_number << "%)");
}

void validate(const IAccessor &tensor, const void *reference_value)
{
    BOOST_TEST_REQUIRE((reference_value != nullptr));

    int64_t      num_mismatches = 0;
    int64_t      num_elements   = 0;
    const size_t channel_size   = element_size_from_data_type(tensor.data_type());

    // Iterate over all elements, e.g. U8, S16, RGB888, ...
    for(int element_idx = 0; element_idx < tensor.num_elements(); ++element_idx)
    {
        const Coordinates id = index2coord(tensor.shape(), element_idx);

        const auto ptr = static_cast<const uint8_t *>(tensor(id));

        // Iterate over all channels within one element
        for(int channel = 0; channel < tensor.num_channels(); ++channel)
        {
            const size_t channel_offset = channel * channel_size;
            const double target         = get_double_data(ptr + channel_offset, tensor.data_type());
            const double ref            = get_double_data(reference_value, tensor.data_type());
            const bool   equal          = is_equal(target, ref);

            BOOST_TEST_INFO("id = " << id);
            BOOST_TEST_INFO("channel = " << channel);
            BOOST_TEST_INFO("reference = " << std::setprecision(5) << ref);
            BOOST_TEST_INFO("target = " << std::setprecision(5) << target);
            BOOST_TEST_WARN(equal);

            if(!equal)
            {
                ++num_mismatches;
            }

            ++num_elements;
        }
    }

    const float percent_mismatches = static_cast<float>(num_mismatches) / num_elements * 100.f;

    BOOST_TEST(num_mismatches == 0,
               num_mismatches << " values (" << std::setprecision(2) << percent_mismatches << "%) mismatched");
}

void validate(const IAccessor &tensor, BorderSize border_size, const BorderMode &border_mode, const void *border_value)
{
    if(border_mode == BorderMode::UNDEFINED)
    {
        return;
    }
    else if(border_mode == BorderMode::CONSTANT)
    {
        BOOST_TEST((border_value != nullptr));
    }

    int64_t   num_mismatches = 0;
    int64_t   num_elements   = 0;
    const int slice_size     = tensor.shape()[0] * tensor.shape()[1];

    for(int element_idx = 0; element_idx < tensor.num_elements(); element_idx += slice_size)
    {
        Coordinates id = index2coord(tensor.shape(), element_idx);

        // Top border
        for(int y = -border_size.top; y < 0; ++y)
        {
            id.set(1, y);

            for(int x = -border_size.left; x < static_cast<int>(tensor.shape()[0]) + static_cast<int>(border_size.right); ++x)
            {
                id.set(0, x);

                check_border_element(tensor, id, border_mode, border_value, num_elements, num_mismatches);
            }
        }

        // Bottom border
        for(int y = tensor.shape()[1]; y < static_cast<int>(tensor.shape()[1]) + static_cast<int>(border_size.bottom); ++y)
        {
            id.set(1, y);

            for(int x = -border_size.left; x < static_cast<int>(tensor.shape()[0]) + static_cast<int>(border_size.right); ++x)
            {
                id.set(0, x);

                check_border_element(tensor, id, border_mode, border_value, num_elements, num_mismatches);
            }
        }

        // Left/right border
        for(int y = 0; y < static_cast<int>(tensor.shape()[1]); ++y)
        {
            id.set(1, y);

            // Left border
            for(int x = -border_size.left; x < 0; ++x)
            {
                id.set(0, x);

                check_border_element(tensor, id, border_mode, border_value, num_elements, num_mismatches);
            }

            // Right border
            for(int x = tensor.shape()[0]; x < static_cast<int>(tensor.shape()[0]) + static_cast<int>(border_size.right); ++x)
            {
                id.set(0, x);

                check_border_element(tensor, id, border_mode, border_value, num_elements, num_mismatches);
            }
        }
    }

    const float percent_mismatches = static_cast<float>(num_mismatches) / num_elements * 100.f;

    BOOST_TEST(num_mismatches == 0,
               num_mismatches << " values (" << std::setprecision(2) << percent_mismatches << "%) mismatched");
}

void validate(std::vector<unsigned int> classified_labels, std::vector<unsigned int> expected_labels)
{
    ARM_COMPUTE_UNUSED(classified_labels);
    ARM_COMPUTE_UNUSED(expected_labels);
    BOOST_TEST(expected_labels.size() != 0);
    BOOST_TEST(classified_labels.size() == expected_labels.size());

    for(unsigned int i = 0; i < expected_labels.size(); ++i)
    {
        BOOST_TEST(classified_labels[i] == expected_labels[i]);
    }
}

void validate(float target, float ref, float tolerance_abs_error, float tolerance_relative_error)
{
    const bool equal = is_equal(target, ref, tolerance_abs_error, tolerance_relative_error);

    BOOST_TEST_INFO("reference = " << std::setprecision(5) << ref);
    BOOST_TEST_INFO("target = " << std::setprecision(5) << target);
    BOOST_TEST(equal);
}

void validate(IArray<KeyPoint> &target, IArray<KeyPoint> &ref, int64_t tolerance)
{
    int64_t num_mismatches = 0;

    BOOST_TEST_WARN(target.num_values() == ref.num_values());

    for(size_t i = 0; i < target.num_values(); ++i)
    {
        KeyPoint *ref_val = std::find_if(ref.buffer(), ref.buffer() + ref.num_values(), [&target, i](KeyPoint key)
        {
            return key.x == target.at(i).x && key.y == target.at(i).y;
        });

        const KeyPoint &key = target.at(i);

        if((ref_val == ref.buffer() + ref.num_values()) || !(is_equal(key.strength, ref_val->strength) && is_equal(key.scale, ref_val->scale) && is_equal(key.orientation, ref_val->orientation)
                                                             && is_equal(key.tracking_status, ref_val->tracking_status) && is_equal(key.error, ref_val->error)))
        {
            ++num_mismatches;

            BOOST_TEST_WARN(is_equal(key.strength, ref_val->strength));
            BOOST_TEST_WARN(is_equal(key.scale, ref_val->scale));
            BOOST_TEST_WARN(is_equal(key.orientation, ref_val->orientation));
            BOOST_TEST_WARN(is_equal(key.tracking_status, ref_val->tracking_status));
            BOOST_TEST_WARN(is_equal(key.error, ref_val->error));
        }
    }

    BOOST_TEST(num_mismatches <= tolerance);
}
} // namespace validation
} // namespace test
} // namespace arm_compute
