/*
 * Copyright (c) 2021,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/AclEntrypoints.h"
#include "arm_compute/AclUtils.h"
#include "arm_compute/core/Error.h"
#include "src/common/ITensorV2.h"
#include "src/common/utils/Macros.h"

namespace
{
using namespace arm_compute;
/**< Maximum allowed dimensions by Compute Library */
constexpr int32_t max_allowed_dims = 6;

/** Check if a descriptor is valid
 *
 * @param desc  Descriptor to validate
 *
 * @return true in case of success else false
 */
bool is_desc_valid(const AclTensorDescriptor &desc)
{
    if(desc.data_type > AclFloat32 || desc.data_type <= AclDataTypeUnknown)
    {
        ARM_COMPUTE_LOG_ERROR_ACL("[AclCreateTensor]: Unknown data type!");
        return false;
    }
    if(desc.ndims > max_allowed_dims)
    {
        ARM_COMPUTE_LOG_ERROR_ACL("[AclCreateTensor]: Dimensions surpass the maximum allowed value!");
        return false;
    }
    if(desc.ndims > 0 && desc.shape == nullptr)
    {
        ARM_COMPUTE_LOG_ERROR_ACL("[AclCreateTensor]: Dimensions values are empty while dimensionality is > 0!");
        return false;
    }
    return true;
}

StatusCode convert_and_validate_tensor(AclTensor tensor, ITensorV2 **internal_tensor)
{
    *internal_tensor = get_internal(tensor);
    return detail::validate_internal_tensor(*internal_tensor);
}
} // namespace

extern "C" AclStatus AclCreateTensor(AclTensor                 *external_tensor,
                                     AclContext                 external_ctx,
                                     const AclTensorDescriptor *desc,
                                     bool                       allocate)
{
    using namespace arm_compute;

    IContext *ctx = get_internal(external_ctx);

    StatusCode status = detail::validate_internal_context(ctx);
    ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status);

    if(desc == nullptr || !is_desc_valid(*desc))
    {
        ARM_COMPUTE_LOG_ERROR_ACL("[AclCreateTensor]: Descriptor is invalid!");
        return AclInvalidArgument;
    }

    auto tensor = ctx->create_tensor(*desc, allocate);
    if(tensor == nullptr)
    {
        ARM_COMPUTE_LOG_ERROR_ACL("[AclCreateTensor]: Couldn't allocate internal resources for tensor creation!");
        return AclOutOfMemory;
    }
    *external_tensor = tensor;

    return AclSuccess;
}

extern "C" AclStatus AclMapTensor(AclTensor external_tensor, void **handle)
{
    using namespace arm_compute;

    auto       tensor = get_internal(external_tensor);
    StatusCode status = detail::validate_internal_tensor(tensor);
    ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status);

    if(handle == nullptr)
    {
        ARM_COMPUTE_LOG_ERROR_ACL("[AclMapTensor]: Handle object is nullptr!");
        return AclInvalidArgument;
    }

    *handle = tensor->map();

    return AclSuccess;
}

extern "C" AclStatus AclUnmapTensor(AclTensor external_tensor, void *handle)
{
    ARM_COMPUTE_UNUSED(handle);

    using namespace arm_compute;

    auto       tensor = get_internal(external_tensor);
    StatusCode status = detail::validate_internal_tensor(tensor);
    ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status);

    status = tensor->unmap();
    return AclSuccess;
}

extern "C" AclStatus AclTensorImport(AclTensor external_tensor, void *handle, AclImportMemoryType type)
{
    using namespace arm_compute;

    auto       tensor = get_internal(external_tensor);
    StatusCode status = detail::validate_internal_tensor(tensor);
    ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status);

    status = tensor->import(handle, utils::as_enum<ImportMemoryType>(type));
    ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status);

    return AclSuccess;
}

extern "C" AclStatus AclDestroyTensor(AclTensor external_tensor)
{
    using namespace arm_compute;

    auto tensor = get_internal(external_tensor);

    StatusCode status = detail::validate_internal_tensor(tensor);
    ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status);

    delete tensor;

    return AclSuccess;
}

extern "C" AclStatus AclGetTensorSize(AclTensor tensor, uint64_t *size)
{
    using namespace arm_compute;

    if(size == nullptr)
    {
        return AclStatus::AclInvalidArgument;
    }

    ITensorV2 *internal_tensor{ nullptr };
    auto       status = convert_and_validate_tensor(tensor, &internal_tensor);
    ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status);

    *size = internal_tensor->get_size();
    return utils::as_cenum<AclStatus>(status);
}

extern "C" AclStatus AclGetTensorDescriptor(AclTensor tensor, AclTensorDescriptor *desc)
{
    using namespace arm_compute;

    if(desc == nullptr)
    {
        return AclStatus::AclInvalidArgument;
    }

    ITensorV2 *internal_tensor{ nullptr };
    const auto status = convert_and_validate_tensor(tensor, &internal_tensor);
    ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status);

    *desc = internal_tensor->get_descriptor();
    return utils::as_cenum<AclStatus>(status);
}