/*
 * Copyright (c) 2017-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 "arm_compute/core/SubTensorInfo.h"

#include "arm_compute/core/Error.h"
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/Validate.h"

namespace arm_compute
{
namespace
{
/** Extends parent shape depending on subtensor's coordinates and shape
 *
 * @param parent_shape Parent shape
 * @param shape        Subtensor shape
 * @param coords       Subtensor coordinates inside parent tensor
 *
 * @return Extended parent shape
 */
TensorShape extend_parent_shape(TensorShape parent_shape, TensorShape shape, Coordinates coords)
{
    // Extend shape
    for(unsigned int i = 0; i < TensorShape::num_max_dimensions; ++i)
    {
        int dimension_extend = coords[i] + static_cast<int>(shape[i]);
        if((dimension_extend > static_cast<int>(parent_shape[i])) && (dimension_extend > 0))
        {
            parent_shape.set(i, static_cast<size_t>(dimension_extend));
        }
    }

    return parent_shape;
}
} // namespace

SubTensorInfo::SubTensorInfo()
    : _parent(nullptr), _tensor_shape(), _dims_state(), _coords(), _valid_region{ Coordinates(), _tensor_shape }, _extend_parent(false), _lock_paddings(false)
{
}

SubTensorInfo::SubTensorInfo(ITensorInfo *parent, TensorShape tensor_shape, Coordinates coords, bool extend_parent)
    : _parent(parent), _tensor_shape(tensor_shape), _dims_state(), _coords(coords), _valid_region{ Coordinates(), _tensor_shape }, _extend_parent(extend_parent), _lock_paddings(false)
{
    ARM_COMPUTE_ERROR_ON(parent == nullptr);

    // Check if subtensor is valid if parent is configured
    if(parent->tensor_shape().total_size() != 0 && !_extend_parent)
    {
        ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(parent->tensor_shape(), coords, tensor_shape);
    }

    // Initialize valid region
    _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
}

std::unique_ptr<ITensorInfo> SubTensorInfo::clone() const
{
    // Clone creates a TensorInfo object from SubTensorInfo's parent which will conclude to a TensorInfo
    // For now it does not make sense to copy a SubTensorInfo explicitly
    ARM_COMPUTE_ERROR_ON(_parent == nullptr);
    auto clone_obj = _parent->clone();
    clone_obj->set_tensor_shape(_tensor_shape);
    clone_obj->set_valid_region(_valid_region);
    return clone_obj;
}

ITensorInfo &SubTensorInfo::set_tensor_shape(const TensorShape &shape)
{
    ARM_COMPUTE_ERROR_ON(_parent == nullptr);

    // Check if subtensor is valid if parent is configured
    if(_parent->tensor_shape().total_size() != 0 && !_extend_parent)
    {
        ARM_COMPUTE_ERROR_ON_INVALID_SUBTENSOR(_parent->tensor_shape(), _coords, shape);
        _valid_region = ValidRegion{ _coords, shape };
    }
    else if(_extend_parent) // Extend parent shape, configure if specified
    {
        ARM_COMPUTE_ERROR_ON((_parent->data_type() == DataType::UNKNOWN) && (_parent->format() == Format::UNKNOWN));
        TensorShape parent_extended_shape = extend_parent_shape(_parent->tensor_shape(), shape, _coords);
        _parent->set_tensor_shape(parent_extended_shape);
        _parent->set_valid_region(ValidRegion{ Coordinates(), parent_extended_shape });
    }
    _tensor_shape = shape;
    return *this;
}

ITensorInfo &SubTensorInfo::set_tensor_dims_state(const TensorDimsState &state)
{
    ARM_COMPUTE_ERROR_ON(_parent == nullptr);
    _dims_state = state;
    return *this;
}

ITensorInfo &SubTensorInfo::set_lock_paddings(bool flag)
{
    _lock_paddings = flag;
    return *this;
}

bool SubTensorInfo::lock_paddings() const
{
    return _lock_paddings;
}

bool SubTensorInfo::extend_padding(const PaddingSize &padding)
{
    ARM_COMPUTE_ERROR_ON(_lock_paddings);
    ARM_COMPUTE_ERROR_ON(_parent == nullptr);
    ARM_COMPUTE_ERROR_ON(!_parent->is_resizable());
    ARM_COMPUTE_ERROR_ON(_parent->total_size() == 0);

    // Check that you do not extend padding on sub-tensors unless XY shape matches parent tensor
    if(!_extend_parent && (padding.left || padding.right))
    {
        ARM_COMPUTE_ERROR_ON(_parent->tensor_shape().x() != tensor_shape().x());
    }
    if(!_extend_parent && (padding.top || padding.bottom))
    {
        ARM_COMPUTE_ERROR_ON(_parent->tensor_shape().y() != tensor_shape().y());
    }

    // Extend parent padding if required
    return _parent->extend_padding(padding);
}

int32_t SubTensorInfo::offset_element_in_bytes(const Coordinates &pos) const
{
    ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(pos, _tensor_shape.num_dimensions());

    int32_t        offset  = offset_first_element_in_bytes();
    const Strides &strides = strides_in_bytes();

    for(size_t i = 0; i < _tensor_shape.num_dimensions(); ++i)
    {
        offset += pos[i] * strides[i];
    }

    return offset;
}
} // namespace arm_compute
