/*
 * Copyright (c) 2021 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/common/utils/LegacySupport.h"

namespace arm_compute
{
namespace detail
{
namespace
{
DataType convert_to_legacy_data_type(AclDataType data_type)
{
    switch(data_type)
    {
        case AclDataType::AclFloat32:
            return DataType::F32;
        case AclDataType::AclFloat16:
            return DataType::F16;
        case AclDataType::AclBFloat16:
            return DataType::BFLOAT16;
        default:
            return DataType::UNKNOWN;
    }
}

AclDataType convert_to_c_data_type(DataType data_type)
{
    switch(data_type)
    {
        case DataType::F32:
            return AclDataType::AclFloat32;
        case DataType::F16:
            return AclDataType::AclFloat16;
        case DataType::BFLOAT16:
            return AclDataType::AclBFloat16;
        default:
            return AclDataType::AclDataTypeUnknown;
    }
}

TensorShape create_legacy_tensor_shape(int32_t ndims, int32_t *shape)
{
    TensorShape legacy_shape{};
    for(int32_t d = 0; d < ndims; ++d)
    {
        legacy_shape.set(d, shape[d], false);
    }
    return legacy_shape;
}
int32_t *create_tensor_shape_array(const TensorInfo &info)
{
    const auto num_dims = info.num_dimensions();
    if(num_dims <= 0)
    {
        return nullptr;
    }

    int32_t *shape_array = new int32_t[num_dims];

    for(size_t d = 0; d < num_dims; ++d)
    {
        shape_array[d] = info.tensor_shape()[d];
    }

    return shape_array;
}
} // namespace

TensorInfo convert_to_legacy_tensor_info(const AclTensorDescriptor &desc)
{
    TensorInfo legacy_desc;
    legacy_desc.init(create_legacy_tensor_shape(desc.ndims, desc.shape), 1, convert_to_legacy_data_type(desc.data_type));
    return legacy_desc;
}

AclTensorDescriptor convert_to_descriptor(const TensorInfo &info)
{
    const auto          num_dims = info.num_dimensions();
    AclTensorDescriptor desc
    {
        static_cast<int32_t>(num_dims),
        create_tensor_shape_array(info),
        convert_to_c_data_type(info.data_type()),
        nullptr,
        0
    };
    return desc;
}
} // namespace detail
} // namespace arm_compute
