/*
 * 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 "src/dynamic_fusion/sketch/gpu/GpuOperatorGroup.h"

#include "arm_compute/core/Validate.h"

namespace arm_compute
{
namespace experimental
{
namespace dynamic_fusion
{
namespace
{
std::vector<DependencyGraph::TensorId> get_tensor_ids(const std::vector<const ITensorInfo *> tensors)
{
    std::vector<DependencyGraph::TensorId> tensor_ids{};
    std::transform(std::begin(tensors), std::end(tensors), std::back_inserter(tensor_ids),
                   [](const auto &t) { return t->id(); });
    return tensor_ids;
}

} // namespace

Operator::Operator(OperatorId id, GpuOperatorType operator_type, const ArgumentPack<ITensorInfo> &tensors)
    : _id{id}, _operator_type{operator_type}, _tensors{tensors}
{
}

OperatorId Operator::id() const
{
    return _id;
}

GpuOperatorType Operator::operator_type() const
{
    return _operator_type;
}

ArgumentPack<ITensorInfo> Operator::tensors() const
{
    return _tensors;
}

bool GpuOperatorGroup::try_add_operator(const Operator &op, bool is_output) const
{
    const auto src_tensor_ids = get_tensor_ids(op.tensors().get_const_src_tensors());
    const auto dst_tensor_ids = get_tensor_ids(op.tensors().get_const_dst_tensors());
    // Constraint 1
    if (!_graph.try_add_operator_as_linear(op.id(), src_tensor_ids, dst_tensor_ids, is_output))
    {
        return false;
    }
    // Constraint 2
    if (_operators.size() >= max_fused_operators)
    {
        return false;
    }
    // Constraint 3.1: Pattern: (Unfusable)
    if (_operators.size() > 0 && get_root_operator()->operator_type() == GpuOperatorType::Unfusable)
    {
        return false;
    }
    // Constraint 3.2
    if (_operators.size() > 0 && (op.operator_type() != GpuOperatorType::Simple))
    {
        return false;
    }
    // Constraint 4
    if (op.operator_type() != GpuOperatorType::Unfusable && op.tensors().get_const_dst_tensors().size() != 1U)
    {
        return false;
    }
    // Constraint 5
    if (_operators.size() > 0)
    {
        const auto root_dst_tensors = get_root_operator()->tensors().get_const_dst_tensors();
        ARM_COMPUTE_ERROR_ON(root_dst_tensors.empty());
        const auto first_dst_tensor = root_dst_tensors[0];
        const auto dst_tensors      = op.tensors().get_const_dst_tensors();
        for (const auto &t : root_dst_tensors)
        {
            if (detail::have_different_dimensions(t->tensor_shape(), first_dst_tensor->tensor_shape(), 0))
            {
                return false;
            }
        }
        for (const auto &t : dst_tensors)
        {
            if (detail::have_different_dimensions(t->tensor_shape(), first_dst_tensor->tensor_shape(), 0))
            {
                return false;
            }
        }
    }
    // Constraint 6
    if (_operators.size() > 0)
    {
        const auto root_dst_tensors = get_root_operator()->tensors().get_const_dst_tensors();
        ARM_COMPUTE_ERROR_ON(root_dst_tensors.empty());
        const auto first_dst_tensor_layout = root_dst_tensors[0]->data_layout();
        const auto dst_tensors             = op.tensors().get_const_dst_tensors();
        for (const auto &t : root_dst_tensors)
        {
            if (t->data_layout() != first_dst_tensor_layout)
            {
                return false;
            }
        }
        for (const auto &t : dst_tensors)
        {
            if (t->data_layout() != first_dst_tensor_layout)
            {
                return false;
            }
        }
    }
    return true;
}
void GpuOperatorGroup::add_operator(const Operator &op, bool is_output)
{
    ARM_COMPUTE_ERROR_ON(!try_add_operator(op, is_output));
    const auto src_tensor_ids = get_tensor_ids(op.tensors().get_const_src_tensors());
    const auto dst_tensor_ids = get_tensor_ids(op.tensors().get_const_dst_tensors());
    _graph.add_operator_as_linear(op.id(), src_tensor_ids, dst_tensor_ids, is_output);
    _operators[op.id()] = op;
}
Operator GpuOperatorGroup::new_operator(const GpuOperatorType           &operator_type,
                                        const ArgumentPack<ITensorInfo> &tensors) const
{
    auto new_id = static_cast<OperatorId>(_operators.size());
    return Operator{new_id, operator_type, tensors};
}
const Operator *GpuOperatorGroup::get_root_operator() const
{
    const auto roots = _graph.get_root_ops();
    ARM_COMPUTE_ERROR_ON(roots.size() > 1);
    if (roots.empty())
    {
        return nullptr;
    }
    return &_operators.at(roots[0]);
}

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