//
// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#include "Layer.hpp"

#include "Graph.hpp"
#include <ProfilingService.hpp>
#include <armnn/utility/NumericCast.hpp>
#include <armnn/backends/TensorHandle.hpp>
#include <armnn/backends/WorkloadData.hpp>

#include <fmt/format.h>

#include <numeric>

namespace armnn
{

// Instantiate the static member variable
NullDescriptor Layer::m_NullDescriptor;

void InputSlot::Insert(Layer& layer)
{
    ARMNN_ASSERT(layer.GetNumOutputSlots() == 1);

    OutputSlot* const prevSlot = GetConnectedOutputSlot();

    if (prevSlot != nullptr)
    {
        // Disconnects parent from this.
        prevSlot->Disconnect(*this);

        // Connects inserted layer to parent.
        ARMNN_ASSERT(layer.GetNumInputSlots() == 1);
        int idx = prevSlot->Connect(layer.GetInputSlot(0));
        prevSlot->SetEdgeStrategy(armnn::numeric_cast<unsigned int>(idx), EdgeStrategy::Undefined);

        // Sets tensor info for inserted layer.
        const TensorInfo& tensorInfo = prevSlot->GetTensorInfo();
        layer.GetOutputHandler().SetTensorInfo(tensorInfo);
    }

    // Connects inserted layer to this.
    layer.GetOutputSlot(0).Connect(*this);
    layer.GetOutputSlot(0).SetEdgeStrategy(0, EdgeStrategy::Undefined);
}

const InputSlot* OutputSlot::GetConnection(unsigned int index) const
{
    ValidateConnectionIndex(index);
    return m_Connections[index];
}

InputSlot* OutputSlot::GetConnection(unsigned int index)
{
    ValidateConnectionIndex(index);
    return m_Connections[index];
}

void OutputSlot::SetTensorInfo(const TensorInfo& tensorInfo)
{
    GetOutputHandler().SetTensorInfo(tensorInfo);
}

const TensorInfo& OutputSlot::GetTensorInfo() const
{
    return GetOutputHandler().GetTensorInfo();
}

bool OutputSlot::IsTensorInfoSet() const
{
    if (GetOwningLayer().GetShapeInferenceMethod() == ShapeInferenceMethod::InferAndValidate)
    {
        GetOwningLayer().ValidateTensorShapesFromInputs();
    }
    return GetOutputHandler().IsTensorInfoSet();
}

bool OutputSlot::ValidateTensorShape(const TensorShape& shape) const
{
    ARMNN_ASSERT_MSG(IsTensorInfoSet(), "TensorInfo must be set in order to validate the shape.");
    return shape == m_OutputHandler.GetTensorInfo().GetShape();
}

int OutputSlot::Connect(InputSlot& destination)
{
    destination.SetConnection(this);
    m_Connections.push_back(&destination);
    m_EdgeStrategies.push_back(EdgeStrategy::Undefined);
    return armnn::numeric_cast<int>(m_Connections.size() - 1);
}

void OutputSlot::Disconnect(InputSlot& slot)
{
    slot.SetConnection(nullptr);
    auto it = std::find(m_Connections.begin(), m_Connections.end(), &slot);

    if (it == m_Connections.end())
    {
        return;
    }

    auto idx = std::distance(m_Connections.begin(), it);
    m_Connections.erase(std::remove(m_Connections.begin(), m_Connections.end(), &slot), m_Connections.end());

    m_EdgeStrategies.erase(m_EdgeStrategies.begin() + idx);
}

void OutputSlot::DisconnectAll()
{
    while (GetNumConnections() > 0)
    {
        InputSlot& connection = *GetConnection(0);
        Disconnect(connection);
    }
}

void OutputSlot::MoveAllConnections(OutputSlot& destination)
{
    while (GetNumConnections() > 0)
    {
        ARMNN_ASSERT_MSG(m_EdgeStrategies[0] == EdgeStrategy::Undefined,
            "Cannot move connections once memory strategies have be established.");

        InputSlot& connection = *GetConnection(0);
        Disconnect(connection);
        destination.Connect(connection);
        destination.GetOutputHandler().SetTensorInfo(GetOutputHandler().GetTensorInfo());
    }
}

unsigned int OutputSlot::CalculateIndexOnOwner() const
{
    for (unsigned int i = 0; i < GetOwningLayer().GetNumOutputSlots(); i++)
    {
        if (GetOwningLayer().GetOutputSlot(i) == (*this))
        {
            return i;
        }
    }
    ARMNN_ASSERT_MSG(false, "Did not find slot on owner.");
    return 0; // Error
}

bool OutputSlot::operator==(const OutputSlot& other) const
{
    bool isSame = other.GetNumConnections() == GetNumConnections();
    if (!isSame)
    {
        return false;
    }

    for (unsigned int i = 0; i < GetNumConnections(); i++)
    {
        isSame &= other.GetConnection(i) == GetConnection(i);
    }
    return isSame;
}

void OutputSlot::ValidateConnectionIndex(unsigned int index) const
{
    if (armnn::numeric_cast<std::size_t>(index) >= m_Connections.size())
    {
        throw InvalidArgumentException((fmt::format("GetConnection: Invalid index {} provided", index)));
    }
}

LayerGuid OutputSlot::GetOwningLayerGuid() const
{
    return GetOwningLayer().GetGuid();
}

void OutputSlot::SetTensorHandleFactory(const ITensorHandleFactory::FactoryId& id)
{
    m_TensorHandleFactoryId = id;
}

ITensorHandleFactory::FactoryId OutputSlot::GetTensorHandleFactoryId() const
{
    return m_TensorHandleFactoryId;
}

void OutputSlot::SetEdgeStrategy(unsigned int connectionIndex, EdgeStrategy strategy)
{
    m_EdgeStrategies[connectionIndex] = strategy;
}

EdgeStrategy OutputSlot::GetEdgeStrategyForConnection(unsigned int connectionIdx) const
{
    return m_EdgeStrategies[connectionIdx];
}

Layer::Layer(unsigned int numInputSlots,
             unsigned int numOutputSlots,
             LayerType type,
             DataLayout layout,
             const char* name)
: m_OutputHandlers(numOutputSlots)
, m_ShapeInferenceMethod(ShapeInferenceMethod::ValidateOnly)
, m_LayerName(name ? name : "")
, m_Type(type)
, m_BackendId()
, m_BackendHint(EmptyOptional())
, m_Guid(arm::pipe::ProfilingService::GetNextGuid())
{
    IgnoreUnused(layout);
    m_InputSlots.reserve(numInputSlots);
    for (unsigned int i = 0; i < numInputSlots; ++i)
    {
        m_InputSlots.emplace_back(*this, i);
    }

    m_OutputSlots.reserve(numOutputSlots);
    for (unsigned int i = 0; i < numOutputSlots; ++i)
    {
        m_OutputSlots.emplace_back(*this, m_OutputHandlers[i]);
    }
}

Layer::Layer(unsigned int numInputSlots,
             unsigned int numOutputSlots,
             LayerType type,
             const char* name)
: Layer(numInputSlots, numOutputSlots, type, DataLayout::NCHW, name)
{
}

void Layer::CollectWorkloadInputs(WorkloadDataCollector& dataCollector) const
{
    for (auto&& inputSlot : GetInputSlots())
    {
        // The graph must be well-formed at this point.
        ARMNN_ASSERT(inputSlot.GetConnection());
        const OutputHandler& outputHandler = inputSlot.GetConnectedOutputSlot()->GetOutputHandler();
        dataCollector.Push(outputHandler.GetData(), outputHandler.GetTensorInfo());
    }
}

void Layer::CollectWorkloadOutputs(WorkloadDataCollector& dataCollector) const
{
    for (auto&& outputHandler : m_OutputHandlers)
    {
        outputHandler.CollectWorkloadOutputs(dataCollector);
    }
}

void Layer::SetAdditionalInfo(QueueDescriptor& descriptor) const
{
    descriptor.m_AdditionalInfoObject = m_AdditionalInfoObject.get();
}

void Layer::CreateTensorHandles(const TensorHandleFactoryRegistry& registry,
                                const IWorkloadFactory& workloadFactory,
                                const bool IsMemoryManaged)
{
    for (unsigned int idx=0; idx < GetNumOutputSlots(); idx++)
    {

        OutputSlot& slot = GetOutputSlot(idx);
        ITensorHandleFactory::FactoryId factoryId = slot.GetTensorHandleFactoryId();

        OutputHandler& handler = GetOutputHandler(idx);
        if (factoryId == ITensorHandleFactory::LegacyFactoryId)
        {
            handler.CreateTensorHandles(workloadFactory, IsMemoryManaged);
        }
        else
        {
            ITensorHandleFactory* handleFactory;
            handleFactory = registry.GetFactory(factoryId);
            ARMNN_ASSERT(handleFactory);
            handler.CreateTensorHandles(*handleFactory, IsMemoryManaged);
        }
    }
}

void Layer::ReleaseConstantData()
{
    // Now free up the static data.
    OperateOnConstantTensors([](std::shared_ptr<ConstTensorHandle>& handle)
                                 {
                                     handle.reset();
                                 });
}

DataType Layer::GetDataType() const
{
    if (GetNumInputSlots() > 0) // Ignore the input layer.
    {
        return GetInputSlot(0).GetConnection()->GetTensorInfo().GetDataType();
    }
    return GetOutputSlot(0).GetTensorInfo().GetDataType();
}

void Layer::ResetPriority() const
{
    m_Priority = 0;
    m_Visiting = false;
}

LayerPriority Layer::GetPriority() const
{
    constexpr LayerPriority inputPrio = std::numeric_limits<LayerPriority>::lowest();
    constexpr LayerPriority outputPrio = std::numeric_limits<LayerPriority>::max();

    if (GetType() == LayerType::Input)
    {
        m_Priority = inputPrio;
    }
    else if (GetType() == LayerType::Output)
    {
        m_Priority = outputPrio;
    }
    else if (m_Priority == 0)
    {
        if (m_Visiting)
        {
            throw GraphValidationException("Graph has circular dependencies: cannot walk");
        }

        auto maxPrio = [](const LayerPriority prio, const InputSlot& slot) -> LayerPriority
            {
                const OutputSlot *outputSlot = slot.GetConnectedOutputSlot();
                if (outputSlot)
                {
                    const Layer& input = outputSlot->GetOwningLayer();
                    return std::max(prio, input.GetPriority());
                }
                else
                {
                    // unconnected input slot
                    return prio;
                }
            };

        m_Visiting = true;
        LayerPriority parentPrio = std::accumulate(GetInputSlots().cbegin(), GetInputSlots().cend(), 0U, maxPrio);
        m_Visiting = false;

        if (parentPrio >= outputPrio)
        {
            throw GraphValidationException("Graph has too many edges");
        }

        m_Priority = parentPrio + 1U;
    }

    return m_Priority;
}

void Layer::VerifyLayerConnections(unsigned int expectedConnections, const CheckLocation& location) const
{
    ARMNN_ASSERT(GetNumInputSlots() == expectedConnections);

    for (unsigned int i=0; i<expectedConnections; ++i)
    {
        if (GetInputSlot(i).GetConnection() == nullptr)
        {
            throw LayerValidationException(
                    fmt::format("Input connection #{0} must be connected "
                                "for {1} layer {2} {3}",
                                i,
                                GetLayerTypeAsCString(this->GetType()),
                                GetNameStr(),
                                location.AsString()));
        }
    }
}

std::vector<TensorShape> Layer::InferOutputShapes(const std::vector<TensorShape>& inputShapes) const
{
    ARMNN_ASSERT(GetNumInputSlots() != 0);
    ARMNN_ASSERT(GetNumOutputSlots() != 0);

    // By default we return what we got, meaning the output shape(s) are the same as the input(s).
    // This only works if the number of inputs and outputs are the same. Since we are in the Layer
    // base class, this means the implementation needs to be overridden in the specific layers for
    // the other cases. So the missing implementation justifies the UnimplementedException.

    if (GetNumInputSlots() != GetNumOutputSlots())
    {
        throw UnimplementedException(
                fmt::format("Default implementation for InferOutputShapes can only be used for "
                            "layers with the same number of input and output slots. This doesn't "
                            "hold for {0} layer {1} (#inputs={2} #outputs={3}) {4}",
                            GetLayerTypeAsCString(this->GetType()),
                            GetNameStr(),
                            GetNumInputSlots(),
                            GetNumOutputSlots(),
                            CHECK_LOCATION().AsString()));
    }
    return inputShapes;
}

void Layer::ValidateAndCopyShape(const TensorShape& outputShape,
                                 const TensorShape& inferredShape,
                                 const ShapeInferenceMethod shapeInferenceMethod,
                                 const std::string& layerName,
                                 const unsigned int outputSlotIndex)
{
    if (shapeInferenceMethod == ShapeInferenceMethod::ValidateOnly)
    {
        ConditionalThrowIfNotEqual<LayerValidationException>(
                layerName + ": TensorShape set on OutputSlot[0] does not match the inferred shape.",
                outputShape,
                inferredShape);
        return;
    }

    if (outputShape.GetDimensionality() == Dimensionality::Specified)
    {
        for (unsigned int i = 0; i < outputShape.GetNumDimensions(); ++i)
        {
            if (outputShape.GetDimensionSpecificity(i) && outputShape[i] != inferredShape[i])
            {
                std::stringstream ss;
                ss << layerName << ": TensorShape set on OutputSlot[" << outputSlotIndex <<
                "] does not match the inferred shape at dimension index [";
                ss << i << "] " << outputShape << " != " << inferredShape;
                throw LayerValidationException(ss.str());
            }
        }
    }

    TensorInfo info = GetOutputSlot(outputSlotIndex).GetTensorInfo();

    armnn::TensorInfo inferredTensorInfo(inferredShape,
                                         info.GetDataType(),
                                         info.GetQuantizationScale(),
                                         info.GetQuantizationOffset());

    GetOutputSlot(outputSlotIndex).SetTensorInfo(inferredTensorInfo);
}

void Layer::VerifyShapeInferenceType(const TensorShape& outputShape, ShapeInferenceMethod shapeInferenceMethod)
{
    if (shapeInferenceMethod == ShapeInferenceMethod::ValidateOnly)
    {
        ConditionalThrow<LayerValidationException>(
                outputShape.GetDimensionality() != Dimensionality::NotSpecified,
                "Dimensionality can not be NotSpecified while using ShapeInferenceMethod::ValidateOnly");

        ConditionalThrow<LayerValidationException>(
                outputShape.AreAllDimensionsSpecified(),
                "Unspecified dimension while using ShapeInferenceMethod::ValidateOnly");
    }
}

void Layer::SerializeLayerParameters(ParameterStringifyFunction& fn) const
{
    std::string guid = std::to_string(m_Guid);
    std::string layerType = GetLayerTypeAsCString(m_Type);
    std::string backendId = std::string(m_BackendId);
    if (!(guid.compare("") == 0) && !guid.empty())
    {
        fn("Guid", guid);
    }
    if(!(m_LayerName.compare("") == 0) && !m_LayerName.empty())
    {
        fn("LayerName",m_LayerName);
    }
    if(!(layerType.compare("") == 0) && !layerType.empty())
    {
        fn("LayerType",layerType);
    }
    if(!(backendId.compare("") == 0) && !backendId.empty())
    {
        fn("BackendID",backendId);
    }
    std::shared_ptr<ActivationDescriptor>
            activationDescPtr = GetAdditionalInformation<ActivationDescriptor>();

    if (activationDescPtr)
    {
        StringifyLayerParameters<ActivationDescriptor>::Serialize(fn, *activationDescPtr.get());
    }
}

// default implementation of ExecuteStrategy
void Layer::ExecuteStrategy(IStrategy& strategy) const
{
    strategy.ExecuteStrategy(this, BaseDescriptor(), {}, GetName());
}

const IConnectableLayer& OutputSlot::GetOwningIConnectableLayer() const
{
    return m_OwningLayer;
}

const IConnectableLayer& InputSlot::GetOwningIConnectableLayer() const
{
    return m_OwningLayer;
}

} // namespace armnn
