//
// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "TransposeConv2dOperator.hpp"

#include "layers/TransposeConvolution2dLayer.hpp"

TosaSerializationBasicBlock* ConvertTransposeConv2dToTosaOperator(const Layer* layer,
                                                                  const std::vector<const TensorInfo*>& inputs,
                                                                  const std::vector<const TensorInfo*>& outputs,
                                                                  const TransposeConvolution2dDescriptor* descriptor)
{
    std::string input0Name = std::string("input0_");
    std::string input1Name = std::string("constant_") + GetUniqueTosaMappingID();
    std::string input2Name = std::string("constant_") + GetUniqueTosaMappingID();
    std::string outputName = std::string("output0_");
    std::string blockName  = std::string("Op_TRANSPOSE_CONV2D_block_") + GetUniqueTosaMappingID();

    // If a layer is present then the block will be used for execution, so input and output names need to be determined
    // using the previous and following layers so the graph is connected correctly. For validation this doesn't matter.
    if(layer != nullptr)
    {
        Layer& connectedInputLayer = layer->GetInputSlot(0).GetConnectedOutputSlot()->GetOwningLayer();
        input0Name = GenerateUniqueName(connectedInputLayer, 0);

        outputName = GenerateUniqueOutputName(*layer, 0);
    }

    std::vector<TosaSerializationTensor*> tensors;
    std::vector<TosaSerializationOperator*> operators;

    // Setup input tensor
    // Only add tensor if connected layer is an input layer.
    // As intermediate or constant tensors will be created separately.
    // There also can't be duplicate tensors.
    if(input0Name.find("input0_") != std::string::npos)
    {
        std::vector<int32_t> inputShape0 = GetTosaTensorShape(inputs[0]->GetShape());
        DType inputDType0 = ArmNNToDType(inputs[0]->GetDataType());

        tensors.push_back(new TosaSerializationTensor(input0Name, inputShape0, inputDType0, {}));
    }

    // Setup weights tensor, constant data will get copied during SetConstantTensorData
    operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {input1Name}));

    // During validation the TensorInfo can be retrieved from the inputs.
    // During execution, it is only available through the layer so use m_Weight.
    if(layer == nullptr)
    {
        std::vector<int32_t> inputShape1 = GetTosaTensorShape(inputs[1]->GetShape());
        DType inputDType1 = ArmNNToDType(inputs[1]->GetDataType());

        tensors.push_back(new TosaSerializationTensor(input1Name, inputShape1, inputDType1, {}));
    }
    else
    {
        auto transposeConv2dLayer = PolymorphicDowncast<const TransposeConvolution2dLayer*>(layer);

        std::vector<int32_t> inputShape1 = GetTosaTensorShape(
                transposeConv2dLayer->m_Weight->GetTensorInfo().GetShape());
        DType inputDType1 = ArmNNToDType(transposeConv2dLayer->m_Weight->GetTensorInfo().GetDataType());

        std::vector<uint8_t> uint8Data = ConvertConstantTensorDataToBuffer(transposeConv2dLayer->m_Weight);
        tensors.push_back(new TosaSerializationTensor(input1Name, inputShape1, inputDType1, uint8Data));
    }

    // Setup bias operator and tensor, constant data will get copied during SetConstantTensorData
    operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {input2Name}));

    // During validation the TensorInfo can be retrieved from the inputs.
    // During execution, it is only available through the layer so use m_Bias.
    if(layer == nullptr && descriptor->m_BiasEnabled)
    {
        std::vector<int32_t> inputShape2 = GetTosaTensorShape(inputs[2]->GetShape());
        DType inputDType2 = ArmNNToDType(inputs[2]->GetDataType());

        tensors.push_back(new TosaSerializationTensor(input2Name, inputShape2, inputDType2, {}));
    }
    else if(descriptor->m_BiasEnabled)
    {
        auto transposeConv2dLayer = PolymorphicDowncast<const TransposeConvolution2dLayer*>(layer);

        std::vector<int32_t> inputShape2 = GetTosaTensorShape(
                transposeConv2dLayer->m_Bias->GetTensorInfo().GetShape());
        DType inputDType2 = ArmNNToDType(transposeConv2dLayer->m_Bias->GetTensorInfo().GetDataType());

        std::vector<uint8_t> uint8Data = ConvertConstantTensorDataToBuffer(transposeConv2dLayer->m_Bias);
        tensors.push_back(new TosaSerializationTensor(input2Name, inputShape2, inputDType2, uint8Data));
    }
    else
    {
        // If bias is disabled, create a constant bias tensor of 0's as three inputs are required.
        // The size of the bias must match the channels dimension, so get the correct index.
        unsigned int index = (descriptor->m_DataLayout == DataLayout::NHWC) ?
                outputs[0]->GetShape()[3] : outputs[0]->GetShape()[1];

        std::vector<uint8_t> uint8Data;
        std::vector<float> data(outputs[0]->GetShape()[index], 0.0f);

        TosaSerializationHandler::ConvertF32toU8(data, uint8Data);

        tensors.push_back(new TosaSerializationTensor(input2Name,
                                                      {static_cast<int32_t>(outputs[0]->GetShape()[index])},
                                                      DType_FP32,
                                                      uint8Data));
    }

    // Setup Output Tensor
    std::vector<int32_t> outputShape0 = GetTosaTensorShape(outputs[0]->GetShape());
    DType outputDType0 = ArmNNToDType(outputs[0]->GetDataType());

    tensors.push_back(new TosaSerializationTensor(outputName, outputShape0, outputDType0, {}));

    // Set up TRANSPOSE_CONV2D operator
    // The TOSA Reference Model pads the output shape, so it is added to output shape.
    // In Arm NN we pad the input shape, so it is taken away.
    // To offset this the negative padding value can be used.
    std::vector<int> pad = {-static_cast<int>(descriptor->m_PadTop),
                            -static_cast<int>(descriptor->m_PadBottom),
                            -static_cast<int>(descriptor->m_PadLeft),
                            -static_cast<int>(descriptor->m_PadRight)};
    std::vector<int> stride = {static_cast<int>(descriptor->m_StrideY),
                               static_cast<int>(descriptor->m_StrideX)};

    std::vector<int> outputShape;
    // If available use shape in descriptor otherwise use output shape.
    if (descriptor->m_OutputShape.size() == 4)
    {
        for (uint32_t i = 0; i < descriptor->m_OutputShape.size(); ++i)
        {
            outputShape.push_back(static_cast<int>(descriptor->m_OutputShape[i]));
        }
    }
    else
    {
        for (uint32_t i = 0; i < outputs[0]->GetNumDimensions(); ++i)
        {
            outputShape.push_back(static_cast<int>(outputs[0]->GetShape()[i]));
        }
    }

    TosaTransposeConvAttribute attribute(pad, stride, outputShape, 0, 0, ArmNNToDType(inputs[0]->GetDataType()));

    auto* op = new TosaSerializationOperator(Op_TRANSPOSE_CONV2D,
                                             Attribute_TransposeConvAttribute,
                                             &attribute,
                                             {input0Name, input1Name, input2Name},
                                             {outputName});
    operators.push_back(op);

    // operatorInputNames/operatorOutputNames ends up being the same as
    // blockInputNames/blockOutputNames for one-to-one ArmNN to TOSA mappings
    return new TosaSerializationBasicBlock(blockName,                            // name
                                           operators,                            // operators
                                           tensors,                              // tensors
                                           {input0Name, input1Name, input2Name}, // inputs
                                           {outputName});                        // outputs
}