/*
 * Copyright (c) 2022 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/dynamic_fusion/sketch/gpu/operators/GpuClamp.h"

#include "arm_compute/core/experimental/Types.h"

#include "src/core/helpers/AutoConfiguration.h"
#include "src/dynamic_fusion/sketch/ArgumentPack.h"
#include "src/dynamic_fusion/sketch/gpu/GpuWorkloadSketchImpl.h"
#include "src/dynamic_fusion/sketch/gpu/components/cl/ClComponentActivation.h"
#include "src/dynamic_fusion/sketch/gpu/template_writer/cl/ClTemplateActivation.h"

#include "src/common/utils/Log.h"

namespace arm_compute
{
namespace experimental
{
namespace dynamic_fusion
{
namespace
{
constexpr GpuOperatorType operator_type = GpuOperatorType::Simple;
} // namespace

Status GpuClamp::is_supported_op(const GpuWorkloadContext &context,
                                 const ITensorInfo        *src,
                                 const ITensorInfo        *dst,
                                 const ClampAttributes    &attributes)
{
    ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, dst);
    ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(src, 1, DataType::F16, DataType::F32);
    ARM_COMPUTE_RETURN_ERROR_ON_MSG(attributes.max_val() < attributes.min_val(), "Maximum clamp value cannot be lower than minimum value");

    // Auto initialize dst tensor info
    TensorInfo dst_info_to_validate = *dst;
    auto_init_if_empty(dst_info_to_validate, *src->clone());

    // CLAMP operator is implemented as LU_BOUNDED_RELU with the alpha and beta variables swapped
    const ClComponentActivation::Attributes act_info{ ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, attributes.max_val(), attributes.min_val() };

    // Check components
    if(context.gpu_language() == GpuLanguage::OpenCL)
    {
        // Validate Activation Component
        const auto properties = IGpuKernelComponent::Properties().stage(UnitWorkloadStage{ UnitWorkloadStage::Stage::Run });

        ArgumentPack<ITensorInfo> arguments;
        arguments.add_const_tensor(ACL_SRC, src);
        arguments.add_const_tensor(ACL_DST, &dst_info_to_validate);
        ARM_COMPUTE_RETURN_ON_ERROR(ClComponentActivation::validate(properties, arguments, act_info));
    }
    else
    {
        ARM_COMPUTE_RETURN_ERROR_MSG("Unimplemented Gpu language");
    }
    return Status{};
}

Status GpuClamp::validate_op(const GpuWorkloadSketch &sketch,
                             const ITensorInfo       *src,
                             const ITensorInfo       *dst,
                             const ClampAttributes   &attributes)
{
    ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, dst);

    // Check if tensors have valid id, i.e. they are created from a sketch
    ARM_COMPUTE_RETURN_ERROR_ON(!src->has_valid_id() || !dst->has_valid_id());

    // Auto initialize dst tensor info
    TensorInfo dst_info_to_validate = *dst;
    auto_init_if_empty(dst_info_to_validate, *src->clone());

    // Perform fusion test to check if the operator meets fusion constraints
    ArgumentPack<ITensorInfo> tensors;
    tensors.add_const_tensor(ACL_SRC, src);
    tensors.add_const_tensor(ACL_DST, &dst_info_to_validate);
    const auto op = sketch.implementation().operator_group().new_operator(operator_type, tensors);
    ARM_COMPUTE_RETURN_ERROR_ON_MSG(!sketch.implementation().operator_group().try_add_operator(op),
                                    "Operator fusion test failed. This operator cannot be fused into the workload");

    // Check if configuration is supported
    return is_supported_op(*sketch.gpu_context(), src, &dst_info_to_validate, attributes);
}

void GpuClamp::create_op(GpuWorkloadSketch     &sketch,
                         ITensorInfo           *src,
                         ITensorInfo           *dst,
                         const ClampAttributes &attributes)
{
    // Assert validation
    ARM_COMPUTE_ERROR_THROW_ON(GpuClamp::validate_op(sketch, src, dst, attributes));
    ARM_COMPUTE_ERROR_ON_NULLPTR(src, dst);
    ARM_COMPUTE_LOG_PARAMS(src, dst, attributes);

    // Auto initialize dst tensor
    auto_init_if_empty(*dst, *src->clone());

    // Translate into components and add to component graph
    GpuKernelComponentGraph &comp_graph = sketch.implementation().component_graph();

    // CLAMP operator is implemented as LU_BOUNDED_RELU with the alpha and beta variables swapped
    const ClComponentActivation::Attributes act_info{ ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, attributes.max_val(), attributes.min_val() };

    const auto *const sketch_ctx = sketch.implementation().context();

    if(sketch_ctx->gpu_language() == GpuLanguage::OpenCL)
    {
        // Add Activation Component
        auto properties = IGpuKernelComponent::Properties();
        properties.stage(UnitWorkloadStage{ UnitWorkloadStage::Stage::Run });

        ArgumentPack<ITensorInfo> arguments;
        arguments.add_const_tensor(ACL_SRC, src);
        arguments.add_const_tensor(ACL_DST, dst);
        comp_graph.add_new_component<ClComponentActivation>(properties, arguments, act_info);
    }
    else
    {
        ARM_COMPUTE_ERROR("Unimplemented Gpu language");
    }

    // Set up fusion test by adding to the Operator Group
    // Note this has to be performed after all the components have been successfully added to the component graph

    // Pack tensor infos
    ArgumentPack<ITensorInfo> tensors;
    tensors.add_const_tensor(ACL_SRC, src);
    tensors.add_const_tensor(ACL_DST, dst);

    const auto op = sketch.implementation().operator_group().new_operator(operator_type, tensors);
    sketch.implementation().operator_group().add_operator(op);
}

} // namespace dynamic_fusion
} // namespace experimental
} // namespace arm_compute
