/*
 * Copyright (c) 2018-2019 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/NEON/functions/NESplit.h"

#include "arm_compute/core/Error.h"
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/ITensor.h"
#include "arm_compute/core/TensorInfo.h"
#include "arm_compute/core/Types.h"
#include "arm_compute/core/utils/misc/ShapeCalculator.h"

#include "support/ToolchainSupport.h"

namespace arm_compute
{
NESplit::NESplit()
    : _outputs_vector(), _slice_functions(), _num_outputs(0)
{
}

void NESplit::configure(const ITensor *input, const std::vector<ITensor *> &outputs, unsigned int axis)
{
    // Create Slice functions
    _num_outputs     = outputs.size();
    _slice_functions = arm_compute::support::cpp14::make_unique<NESlice[]>(_num_outputs);

    // Get output shape
    const TensorShape output_shape = arm_compute::misc::shape_calculator::compute_split_shape(input->info(), axis, _num_outputs);

    // Extract output tensor info
    std::vector<ITensorInfo *> outputs_info;
    for(auto &output : outputs)
    {
        ARM_COMPUTE_ERROR_ON_NULLPTR(output);
        outputs_info.emplace_back(output->info());
    }

    // Validate
    ARM_COMPUTE_ERROR_THROW_ON(NESplit::validate(input->info(), outputs_info, axis));

    const size_t axis_split_step = output_shape[axis];
    unsigned int axis_offset     = 0;

    // Start/End coordinates
    Coordinates start_coords;
    Coordinates end_coords;
    for(unsigned int d = 0; d < output_shape.num_dimensions(); ++d)
    {
        end_coords.set(d, -1);
    }

    for(unsigned int i = 0; i < _num_outputs; i++)
    {
        // Update coordinate on axis
        start_coords.set(axis, axis_offset);
        end_coords.set(axis, axis_offset + axis_split_step);

        // Configure slice function
        _slice_functions[i].configure(input, outputs[i], start_coords, end_coords);

        // Set valid region from shape
        outputs[i]->info()->set_valid_region(ValidRegion(Coordinates(), output_shape));

        // Update axis offset
        axis_offset += axis_split_step;
    }
}

Status NESplit::validate(const ITensorInfo *input, const std::vector<ITensorInfo *> &outputs, unsigned int axis)
{
    ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input);
    ARM_COMPUTE_RETURN_ERROR_ON(axis >= input->num_dimensions());
    ARM_COMPUTE_RETURN_ERROR_ON(outputs.size() < 2);

    // Get output shape
    const TensorShape output_shape = arm_compute::misc::shape_calculator::compute_split_shape(input, axis, outputs.size());
    ARM_COMPUTE_RETURN_ERROR_ON(output_shape.total_size() == 0);

    const size_t axis_split_step = output_shape[axis];
    unsigned int axis_offset     = 0;

    // Start/End coordinates
    Coordinates start_coords;
    Coordinates end_coords;
    for(unsigned int d = 0; d < output_shape.num_dimensions(); ++d)
    {
        end_coords.set(d, -1);
    }

    // Validate output tensors
    for(const auto &output : outputs)
    {
        ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(output);

        // Output auto inizialitation if not yet initialized
        TensorInfo tmp_output_info = *output->clone();
        auto_init_if_empty(tmp_output_info, input->clone()->set_is_resizable(true).set_tensor_shape(output_shape));

        // Update coordinate on axis
        start_coords.set(axis, axis_offset);
        end_coords.set(axis, axis_offset + axis_split_step);

        ARM_COMPUTE_RETURN_ON_ERROR(NESlice::validate(input, output, start_coords, end_coords));
        axis_offset += axis_split_step;
    }

    return Status{};
}

void NESplit::run()
{
    for(unsigned i = 0; i < _num_outputs; ++i)
    {
        _slice_functions[i].run();
    }
}
} // namespace arm_compute
