/*
 * Copyright (c) 2021-2023 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 "src/cpu/operators/CpuScale.h"

#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/TensorInfo.h"
#include "arm_compute/runtime/NEON/NEScheduler.h"

#include "src/common/utils/Log.h"
#include "src/core/utils/ScaleUtils.h"
#include "src/cpu/kernels/CpuScaleKernel.h"
#include "support/Rounding.h"

namespace arm_compute
{
namespace cpu
{
namespace
{
void precompute_dx_dy_offsets(
    ITensor *dx, ITensor *dy, ITensor *offsets, float wr, float hr, SamplingPolicy sampling_policy, bool align_corners)
{
    ARM_COMPUTE_ERROR_ON(offsets == nullptr);
    float sampling_offset = 0.0f;
    if (sampling_policy == SamplingPolicy::CENTER)
    {
        sampling_offset = 0.5f;
    }

    Window win;
    win.set(Window::DimX, Window::Dimension(0, offsets->info()->dimension(0), 1));
    win.set(Window::DimY, Window::Dimension(0, offsets->info()->dimension(1), 1));

    if (dx != nullptr && dy != nullptr)
    {
        // Pre-compute the offset and pixel's distance for BILINEAR interpolation
        Iterator offsets_it(offsets, win);
        Iterator dx_it(dx, win);
        Iterator dy_it(dy, win);

        execute_window_loop(
            win,
            [&](const Coordinates &id)
            {
                const float in_x  = (id.x() + sampling_offset) * wr - sampling_offset;
                const float in_y  = (id.y() + sampling_offset) * hr - sampling_offset;
                const int   in_xi = std::floor(in_x);
                const int   in_yi = std::floor(in_y);

                *reinterpret_cast<int32_t *>(offsets_it.ptr()) = in_xi;
                *reinterpret_cast<float *>(dx_it.ptr())        = in_x - in_xi;
                *reinterpret_cast<float *>(dy_it.ptr())        = in_y - in_yi;
            },
            offsets_it, dx_it, dy_it);
    }
    else
    {
        // Pre-compute the offset for NEAREST interpolation
        Iterator offsets_it(offsets, win);

        execute_window_loop(
            win,
            [&](const Coordinates &id)
            {
                const float float_in_xi = (id.x() + sampling_offset) * wr;
                const auto  in_xi       = static_cast<size_t>(
                    align_corners ? arm_compute::utils::rounding::round_half_away_from_zero(float_in_xi)
                                         : std::floor(float_in_xi));
                *reinterpret_cast<int32_t *>(offsets_it.ptr()) = in_xi;
            },
            offsets_it);
    }
}
} // namespace

void CpuScale::configure(ITensorInfo *src, ITensorInfo *dst, const ScaleKernelInfo &info)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(src, dst);
    ARM_COMPUTE_ERROR_THROW_ON(CpuScale::validate(src, dst, info));
    ARM_COMPUTE_LOG_PARAMS(src, dst, info);

    _scale_info  = info;
    _is_prepared = false;

    // Get data layout and width/height indices
    _data_layout        = _scale_info.data_layout == DataLayout::UNKNOWN ? src->data_layout() : _scale_info.data_layout;
    const int idx_width = get_data_layout_dimension_index(_data_layout, DataLayoutDimension::WIDTH);
    const int idx_height = get_data_layout_dimension_index(_data_layout, DataLayoutDimension::HEIGHT);

    // Compute the ratio between source width/height and destination width/height
    const bool is_align_corners_used =
        _scale_info.align_corners &&
        arm_compute::scale_utils::is_align_corners_allowed_sampling_policy(_scale_info.sampling_policy);
    const auto wr = arm_compute::scale_utils::calculate_resize_ratio(src->dimension(idx_width),
                                                                     dst->dimension(idx_width), is_align_corners_used);
    const auto hr = arm_compute::scale_utils::calculate_resize_ratio(src->dimension(idx_height),
                                                                     dst->dimension(idx_height), is_align_corners_used);

    // Area interpolation behaves as Nearest Neighbour in case of up-sampling
    InterpolationPolicy policy_to_use =
        (_scale_info.interpolation_policy == InterpolationPolicy::AREA && wr <= 1.f && hr <= 1.f)
            ? InterpolationPolicy::NEAREST_NEIGHBOR
            : _scale_info.interpolation_policy;

    // Get the tensor shape
    TensorShape shape(dst->dimension(idx_width));
    shape.set(1, dst->dimension(idx_height), false);

    TensorInfo tensor_info_offsets(shape, Format::S32);
    TensorInfo tensor_info_dxdy(shape, Format::F32);

    auto dx           = std::make_unique<TensorInfo>(tensor_info_dxdy);
    auto dy           = std::make_unique<TensorInfo>(tensor_info_dxdy);
    auto offsets      = std::make_unique<TensorInfo>(tensor_info_offsets);
    auto scale_kernel = std::make_unique<kernels::CpuScaleKernel>();
    switch (policy_to_use)
    {
        case InterpolationPolicy::NEAREST_NEIGHBOR:
        {
            scale_kernel->configure(src, nullptr, nullptr, offsets.get(), dst, info);
            break;
        }
        case InterpolationPolicy::BILINEAR:
        {
            scale_kernel->configure(src, dx.get(), dy.get(), offsets.get(), dst, info);
            break;
        }
        case InterpolationPolicy::AREA:
        {
            scale_kernel->configure(src, nullptr, nullptr, nullptr, dst, info);
            break;
        }
        default:
            ARM_COMPUTE_ERROR("Unsupported interpolation mode");
    }
    _kernel = std::move(scale_kernel);
}

Status CpuScale::validate(const ITensorInfo *src, const ITensorInfo *dst, const ScaleKernelInfo &info)
{
    ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, dst);
    ARM_COMPUTE_RETURN_ERROR_ON(info.sampling_policy != SamplingPolicy::CENTER &&
                                info.sampling_policy != SamplingPolicy::TOP_LEFT);

    ITensorInfo *offsets = nullptr;
    ITensorInfo *dx      = nullptr;
    ITensorInfo *dy      = nullptr;

    // Get data layout and width/height indices
    const DataLayout data_layout = info.data_layout == DataLayout::UNKNOWN ? src->data_layout() : info.data_layout;
    const int        idx_width   = get_data_layout_dimension_index(data_layout, DataLayoutDimension::WIDTH);
    const int        idx_height  = get_data_layout_dimension_index(data_layout, DataLayoutDimension::HEIGHT);

    // Compute the ratio between source width/height and destination width/height
    const bool is_align_corners_used =
        info.align_corners && arm_compute::scale_utils::is_align_corners_allowed_sampling_policy(info.sampling_policy);
    const auto wr = arm_compute::scale_utils::calculate_resize_ratio(src->dimension(idx_width),
                                                                     dst->dimension(idx_width), is_align_corners_used);
    const auto hr = arm_compute::scale_utils::calculate_resize_ratio(src->dimension(idx_height),
                                                                     dst->dimension(idx_height), is_align_corners_used);

    // Area interpolation behaves as Nearest Neighbour in case of up-sampling
    InterpolationPolicy policy_to_use =
        (info.interpolation_policy == InterpolationPolicy::AREA && wr <= 1.f && hr <= 1.f)
            ? InterpolationPolicy::NEAREST_NEIGHBOR
            : info.interpolation_policy;

    // Get the tensor shape of auxilary buffers
    const TensorShape shape(dst->dimension(idx_width), dst->dimension(idx_height));
    TensorInfo        tensor_info_offsets(shape, Format::S32);
    TensorInfo        tensor_info_dx(shape, Format::F32);
    TensorInfo        tensor_info_dy(shape, Format::F32);
    switch (policy_to_use)
    {
        case InterpolationPolicy::NEAREST_NEIGHBOR:
            offsets = &tensor_info_offsets;
            break;
        case InterpolationPolicy::BILINEAR:
            offsets = &tensor_info_offsets;
            dx      = &tensor_info_dx;
            dy      = &tensor_info_dy;
            break;
        default:
            break;
    }

    ARM_COMPUTE_RETURN_ON_ERROR(
        kernels::CpuScaleKernel::validate(src->clone().get(), dx, dy, offsets, dst->clone().get(), info));
    return Status{};
}

void CpuScale::prepare(ITensorPack &tensors)
{
    if (!_is_prepared)
    {
        _is_prepared       = true;
        const auto src     = tensors.get_const_tensor(TensorType::ACL_SRC);
        auto       dst     = tensors.get_tensor(TensorType::ACL_DST);
        auto       dx      = tensors.get_tensor(TensorType::ACL_INT_0);
        auto       dy      = tensors.get_tensor(TensorType::ACL_INT_1);
        auto       offsets = tensors.get_tensor(TensorType::ACL_INT_2);

        // Get data layout and width/height indices
        const int idx_width  = get_data_layout_dimension_index(_data_layout, DataLayoutDimension::WIDTH);
        const int idx_height = get_data_layout_dimension_index(_data_layout, DataLayoutDimension::HEIGHT);

        // Compute the ratio between source width/height and destination width/height
        const bool is_align_corners_used =
            _scale_info.align_corners &&
            arm_compute::scale_utils::is_align_corners_allowed_sampling_policy(_scale_info.sampling_policy);
        const auto wr = arm_compute::scale_utils::calculate_resize_ratio(
            src->info()->dimension(idx_width), dst->info()->dimension(idx_width), is_align_corners_used);
        const auto hr = arm_compute::scale_utils::calculate_resize_ratio(
            src->info()->dimension(idx_height), dst->info()->dimension(idx_height), is_align_corners_used);

        // Area interpolation behaves as Nearest Neighbour in case of up-sampling
        InterpolationPolicy policy_to_use =
            (_scale_info.interpolation_policy == InterpolationPolicy::AREA && wr <= 1.f && hr <= 1.f)
                ? InterpolationPolicy::NEAREST_NEIGHBOR
                : _scale_info.interpolation_policy;
        const SamplingPolicy sampling_policy = _scale_info.sampling_policy;

        bool precompute_indices_weights = arm_compute::scale_utils::is_precomputation_required(
            _data_layout, src->info()->data_type(), policy_to_use, _scale_info.border_mode);

        if (precompute_indices_weights)
        {
            switch (policy_to_use)
            {
                case InterpolationPolicy::NEAREST_NEIGHBOR:
                {
                    // Pre-compute offsets for nearest interpolation
                    precompute_dx_dy_offsets(nullptr, nullptr, offsets, wr, hr, sampling_policy, is_align_corners_used);
                    break;
                }
                case InterpolationPolicy::BILINEAR:
                {
                    // Pre-compute dx, dy and offsets for bilinear interpolation
                    precompute_dx_dy_offsets(dx, dy, offsets, wr, hr, sampling_policy, is_align_corners_used);
                    break;
                }
                case InterpolationPolicy::AREA:
                {
                    break;
                }
                default:
                    ARM_COMPUTE_ERROR("Unsupported interpolation mode");
            }
        }
        else
        {
            if (policy_to_use != InterpolationPolicy::NEAREST_NEIGHBOR &&
                policy_to_use != InterpolationPolicy::BILINEAR && policy_to_use != InterpolationPolicy::AREA)
            {
                ARM_COMPUTE_ERROR("Unsupported interpolation mode");
            }
        }
    }
}

void CpuScale::run(ITensorPack &tensors)
{
    ARM_COMPUTE_ERROR_ON_MSG(tensors.empty(), "No inputs provided");
    prepare(tensors);
    NEScheduler::get().schedule_op(_kernel.get(), Window::DimY, _kernel->window(), tensors);
}
} // namespace cpu
} // namespace arm_compute
