/*
 * Copyright (c) 2019-2020 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 "arm_compute/runtime/CL/functions/CLCropResize.h"

#include "arm_compute/core/CL/CLHelpers.h"
#include "arm_compute/runtime/CL/CLScheduler.h"
#include "src/core/helpers/AutoConfiguration.h"
#include "src/core/helpers/WindowHelpers.h"

#include "support/MemorySupport.h"

#include <cstddef>

namespace arm_compute
{
namespace
{
inline void configure_crop(const ICLTensor *input, ICLTensor *crop_boxes, ICLTensor *box_ind, ICLTensor *output, uint32_t crop_box_ind, Coordinates &start, Coordinates &end, uint32_t &batch_index)
{
    batch_index = *(reinterpret_cast<int32_t *>(box_ind->ptr_to_element(Coordinates(crop_box_ind))));

    // _crop_box_ind is used to index crop_boxes and retrieve the appropriate crop box.
    // The crop box is specified by normalized coordinates [y0, x0, y1, x1].
    const float x0 = *reinterpret_cast<const float *>(crop_boxes->ptr_to_element(Coordinates(1, crop_box_ind)));
    const float y0 = *reinterpret_cast<const float *>(crop_boxes->ptr_to_element(Coordinates(0, crop_box_ind)));
    const float x1 = *reinterpret_cast<const float *>(crop_boxes->ptr_to_element(Coordinates(3, crop_box_ind)));
    const float y1 = *reinterpret_cast<const float *>(crop_boxes->ptr_to_element(Coordinates(2, crop_box_ind)));
    // The normalized coordinates are scaled to retrieve the floating point image coordinates which are rounded to integers.
    start = Coordinates(std::floor(x0 * (input->info()->tensor_shape()[1] - 1) + 0.5f),
                        std::floor(y0 * (input->info()->tensor_shape()[2] - 1) + 0.5f));
    end = Coordinates(std::floor(x1 * (input->info()->tensor_shape()[1] - 1) + 0.5f),
                      std::floor(y1 * (input->info()->tensor_shape()[2] - 1) + 0.5f));
    const TensorShape out_shape(input->info()->tensor_shape()[0], static_cast<uint32_t>(abs(end[0] - start[0])) + 1, static_cast<uint32_t>(abs(end[1] - start[1])) + 1);
    output->info()->set_tensor_shape(out_shape);
}
} // namespace

CLCropResize::CLCropResize()
    : _input(nullptr), _boxes(nullptr), _box_ind(nullptr), _output(nullptr), _num_boxes(0), _method(), _extrapolation_value(0), _scale(), _copy(), _crop_results(), _scaled_results(), _internal_kernels()
{
}

Status CLCropResize::validate(const ITensorInfo *input, ITensorInfo *boxes, ITensorInfo *box_ind, const ITensorInfo *output,
                              Coordinates2D crop_size, InterpolationPolicy method, float extrapolation_value)
{
    ARM_COMPUTE_RETURN_ERROR_ON(crop_size.x <= 0 || crop_size.y <= 0);
    ARM_COMPUTE_RETURN_ERROR_ON(method == InterpolationPolicy::AREA);
    ARM_COMPUTE_RETURN_ERROR_ON(boxes->tensor_shape()[0] != 4);
    ARM_COMPUTE_RETURN_ERROR_ON(boxes->tensor_shape()[1] != box_ind->tensor_shape()[0]);
    TensorInfo temp_info;
    ARM_COMPUTE_RETURN_ON_ERROR(CLCropKernel::validate(input->clone().get(), &temp_info, { 0, 0 }, { 1, 1 }, input->dimension(3) - 1, extrapolation_value));
    if(output->total_size() > 0)
    {
        ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(output, DataType::F32);
        ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(input, output);
        TensorShape out_shape(input->tensor_shape()[0], crop_size.x, crop_size.y, boxes->tensor_shape()[1]);
        ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output->tensor_shape(), out_shape);
    }
    return Status{};
}

void CLCropResize::configure(const ICLTensor *input, ICLTensor *boxes, ICLTensor *box_ind, ICLTensor *output, Coordinates2D crop_size,
                             InterpolationPolicy method, float extrapolation_value)
{
    configure(CLKernelLibrary::get().get_compile_context(), input, boxes, box_ind, output, crop_size, method, extrapolation_value);
}

void CLCropResize::configure(const CLCompileContext &compile_context, const ICLTensor *input, ICLTensor *boxes, ICLTensor *box_ind, ICLTensor *output, Coordinates2D crop_size,
                             InterpolationPolicy method, float extrapolation_value)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(input, output, boxes, box_ind);
    ARM_COMPUTE_ERROR_THROW_ON(CLCropResize::validate(input->info(), boxes->info(), box_ind->info(), output->info(), crop_size, method, extrapolation_value));

    TensorShape output_shape = TensorShape(input->info()->tensor_shape()[0], crop_size.x, crop_size.y, boxes->info()->tensor_shape()[1]);
    auto_init_if_empty(*output->info(), output_shape, 1, DataType::F32);

    _num_boxes = boxes->info()->tensor_shape()[1];
    TensorShape out_shape(input->info()->tensor_shape()[0], crop_size.x, crop_size.y);

    _input               = input;
    _boxes               = boxes;
    _box_ind             = box_ind;
    _output              = output;
    _method              = method;
    _extrapolation_value = extrapolation_value;

    // For each crop box:
    // - The initial cropped image is produced as specified by boxes[i] from the 3D image input[box_ind[i]].
    //   Possibly using a CLCropKernel and up to four CLMemsetKernels.
    // - A tensor is required to hold this initial cropped image.
    // - A scale function is used to resize the cropped image to the size specified by crop_size.
    // - A tensor is required to hold the final scaled image before it is copied into the 4D output
    //   that will hold all final cropped and scaled 3D images using CLCopyKernel.

    // The contents of _boxes and _box_ind are required to calculate the shape
    // of the initial cropped image and thus are required to configure the
    // kernels used for cropping and scaling.
    _boxes->map(CLScheduler::get().queue());
    _box_ind->map(CLScheduler::get().queue());
    for(unsigned int num_box = 0; num_box < _num_boxes; ++num_box)
    {
        auto       crop_tensor = support::cpp14::make_unique<CLTensor>();
        TensorInfo crop_result_info(1, DataType::F32);
        crop_result_info.set_data_layout(DataLayout::NHWC);
        crop_tensor->allocator()->init(crop_result_info);
        _crop_results.emplace_back(std::move(crop_tensor));

        auto       scale_tensor = support::cpp14::make_unique<CLTensor>();
        TensorInfo scaled_result_info(out_shape, 1, DataType::F32);
        scaled_result_info.set_data_layout(DataLayout::NHWC);
        scale_tensor->allocator()->init(scaled_result_info);
        _scaled_results.emplace_back(std::move(scale_tensor));

        // Size of the crop box in _boxes has to be given before the configure
        uint32_t    batch_index;
        Coordinates start{};
        Coordinates end{};
        configure_crop(_input, _boxes, _box_ind, _crop_results[num_box].get(), num_box, start, end, batch_index);

        auto scale_kernel = support::cpp14::make_unique<CLScale>();
        scale_kernel->configure(compile_context, _crop_results[num_box].get(), _scaled_results[num_box].get(), ScaleKernelInfo{ _method, BorderMode::CONSTANT, PixelValue(_extrapolation_value), SamplingPolicy::TOP_LEFT });
        _scale.emplace_back(std::move(scale_kernel));

        Window win = calculate_max_window(*_output->info());
        win.set(3, Window::Dimension(num_box, num_box + 1, 1));

        auto copy_kernel = support::cpp14::make_unique<CLCopyKernel>();
        copy_kernel->configure(compile_context, _scaled_results[num_box].get(), _output, &win);
        _copy.emplace_back(std::move(copy_kernel));

        _crop_results[num_box]->allocator()->allocate();
        _scaled_results[num_box]->allocator()->allocate();

        bool is_width_flipped  = end[0] < start[0];
        bool is_height_flipped = end[1] < start[1];
        /** The number of rows out of bounds at the start and end of _crop_results[num_box].get(). */
        std::array<int32_t, 2> rows_out_of_bounds{ 0 };
        /** The number of columns out of bounds at the start and end of _crop_results[num_box].get(). */
        std::array<int32_t, 2> cols_out_of_bounds{ 0 };
        if(is_height_flipped)
        {
            rows_out_of_bounds[0] = start[1] >= static_cast<int32_t>(_input->info()->dimension(2)) ? std::min(start[1] - _input->info()->dimension(2) + 1, _crop_results[num_box].get()->info()->dimension(2)) : 0;
            rows_out_of_bounds[1] = end[1] < 0 ? std::min(-end[1], static_cast<int32_t>(_crop_results[num_box].get()->info()->dimension(2))) : 0;
        }
        else
        {
            rows_out_of_bounds[0] = start[1] < 0 ? std::min(-start[1], static_cast<int32_t>(_crop_results[num_box].get()->info()->dimension(2))) : 0;
            rows_out_of_bounds[1] = end[1] >= static_cast<int32_t>(_input->info()->dimension(2)) ? std::min(end[1] - _input->info()->dimension(2) + 1, _crop_results[num_box].get()->info()->dimension(2)) : 0;
        }
        if(is_width_flipped)
        {
            cols_out_of_bounds[0] = start[0] >= static_cast<int32_t>(_input->info()->dimension(1)) ? std::min(start[0] - _input->info()->dimension(1) + 1, _crop_results[num_box].get()->info()->dimension(1)) : 0;
            cols_out_of_bounds[1] = end[0] < 0 ? std::min(-end[0], static_cast<int32_t>(_crop_results[num_box].get()->info()->dimension(1))) : 0;
        }
        else
        {
            cols_out_of_bounds[0] = start[0] < 0 ? std::min(-start[0], static_cast<int32_t>(_crop_results[num_box].get()->info()->dimension(1))) : 0;
            cols_out_of_bounds[1] = end[0] >= static_cast<int32_t>(_input->info()->dimension(1)) ? std::min(end[0] - _input->info()->dimension(1) + 1, _crop_results[num_box].get()->info()->dimension(1)) : 0;
        }

        Window full_window = calculate_max_window(*_crop_results[num_box].get()->info());

        //  Full _crop_results[num_box].get() window:
        //  --------------------------------
        //  |          Out of bounds       |
        //  |          rows before         |
        //  |------------------------------|
        //  | Out of | In         | Out of |
        //  | bounds | bounds     | bounds |
        //  | cols   | elements   | cols   |
        //  | before | copied     | after  |
        //  |        | from input |        |
        //  |------------------------------|
        //  |        Out of bounds         |
        //  |        rows after            |
        //  |------------------------------|
        // Use a separate _crop_results[num_box].get() window for each section of the full _crop_results[num_box].get() window.
        // Fill all _crop_results[num_box].get() rows that have no elements that are within the input bounds
        // with the extrapolation value using memset.
        // First for the rows before the in bounds rows.
        if(rows_out_of_bounds[0] > 0)
        {
            Window slice_fill_rows_before(full_window);
            slice_fill_rows_before.set(2, Window::Dimension(0, rows_out_of_bounds[0], 1));
            auto kernel = arm_compute::support::cpp14::make_unique<CLMemsetKernel>();
            kernel->configure(compile_context, _crop_results[num_box].get(), extrapolation_value, &slice_fill_rows_before);
            _internal_kernels.push_back(std::move(kernel));
        }

        Window slice_in(full_window);
        slice_in.set(2, Window::Dimension(rows_out_of_bounds[0], _crop_results[num_box].get()->info()->dimension(2) - rows_out_of_bounds[1], 1));
        slice_in.set(1, Window::Dimension(cols_out_of_bounds[0], _crop_results[num_box].get()->info()->dimension(1) - cols_out_of_bounds[1], 1));

        int rows_in_bounds = static_cast<int32_t>(_crop_results[num_box].get()->info()->dimension(2)) - rows_out_of_bounds[0] - rows_out_of_bounds[1];
        if(rows_in_bounds > 0)
        {
            // Fill all elements that share a row with an in bounds element with the extrapolation value.
            if(cols_out_of_bounds[0] > 0)
            {
                Window slice_fill_cols_before(slice_in);
                slice_fill_cols_before.set(1, Window::Dimension(0, cols_out_of_bounds[0], 1));
                auto kernel = arm_compute::support::cpp14::make_unique<CLMemsetKernel>();
                kernel->configure(compile_context, _crop_results[num_box].get(), extrapolation_value, &slice_fill_cols_before);
                _internal_kernels.push_back(std::move(kernel));
            }

            if(cols_out_of_bounds[1] > 0)
            {
                Window slice_fill_cols_after(slice_in);
                slice_fill_cols_after.set(1, Window::Dimension(_crop_results[num_box].get()->info()->dimension(1) - cols_out_of_bounds[1], _crop_results[num_box].get()->info()->dimension(1), 1));
                auto kernel = arm_compute::support::cpp14::make_unique<CLMemsetKernel>();
                kernel->configure(compile_context, _crop_results[num_box].get(), extrapolation_value, &slice_fill_cols_after);
                _internal_kernels.push_back(std::move(kernel));
            }

            // Copy all elements within the input bounds from the input tensor.
            int cols_in_bounds = static_cast<int32_t>(_crop_results[num_box].get()->info()->dimension(1)) - cols_out_of_bounds[0] - cols_out_of_bounds[1];
            if(cols_in_bounds > 0)
            {
                Coordinates2D start_in{ is_width_flipped ? start[0] - cols_out_of_bounds[0] : start[0] + cols_out_of_bounds[0],
                                        is_height_flipped ? start[1] - rows_out_of_bounds[0] : start[1] + rows_out_of_bounds[0] };
                Coordinates2D end_in{ is_width_flipped ? start_in.x - cols_in_bounds + 1 : start_in.x + cols_in_bounds - 1,
                                      is_height_flipped ? start_in.y - rows_in_bounds + 1 : start_in.y + rows_in_bounds - 1 };
                auto kernel = arm_compute::support::cpp14::make_unique<CLCropKernel>();

                kernel->configure(compile_context, _input, _crop_results[num_box].get(), start_in, end_in, batch_index, extrapolation_value, &slice_in);
                _internal_kernels.push_back(std::move(kernel));
            }
        }

        // Fill all rows after the in bounds elements with the extrapolation value.
        if(rows_out_of_bounds[1] > 0)
        {
            Window slice_fill_rows_after(full_window);
            slice_fill_rows_after.set(2, Window::Dimension(_crop_results[num_box].get()->info()->dimension(2) - rows_out_of_bounds[1], _crop_results[num_box].get()->info()->dimension(2), 1));
            auto kernel = arm_compute::support::cpp14::make_unique<CLMemsetKernel>();
            kernel->configure(compile_context, _crop_results[num_box].get(), extrapolation_value, &slice_fill_rows_after);
            _internal_kernels.push_back(std::move(kernel));
        }
    }
    _boxes->unmap(CLScheduler::get().queue());
    _box_ind->unmap(CLScheduler::get().queue());
    CLScheduler::get().sync();
}

void CLCropResize::run()
{
    ARM_COMPUTE_ERROR_ON_MSG(_output == nullptr, "Unconfigured function");

    for(unsigned int i = 0; i < _internal_kernels.size(); ++i)
    {
        CLScheduler::get().enqueue(*(_internal_kernels[i]));
    }

    CLScheduler::get().sync();
    for(auto &kernel : _scale)
    {
        kernel->run();
    }
    CLScheduler::get().sync();
    for(auto &kernel : _copy)
    {
        CLScheduler::get().enqueue(*kernel, true);
    }
    CLScheduler::get().sync();
}
} // namespace arm_compute