/*
 * Copyright (c) 2021-2022 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/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
