/**
 * Copyright 2023 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "rde_update_utils.hpp"

#include "libbej/bej_common.h"
#include "libbej/bej_dictionary.h"

#include "libbej/bej_encoder_json.hpp"
#include "nlohmann/json.hpp"

#include <helper/common.hpp>

#include <cstring>
#include <iostream>
#include <sstream>
#include <unordered_map>
#include <variant>

using json = nlohmann::json;
using BejChildNodesVariant =
    std::variant<struct RedfishPropertyParent, struct RedfishPropertyLeafNull,
                 struct RedfishPropertyLeafInt, struct RedfishPropertyLeafEnum,
                 struct RedfishPropertyLeafString,
                 struct RedfishPropertyLeafReal,
                 struct RedfishPropertyLeafBool>;

static int addLeafToBejTree(
    const struct BejDictionaryProperty* property,
    const std::string& propertyName, json& propertyValue,
    struct RedfishPropertyParent* root,
    std::unordered_map<std::string, BejChildNodesVariant>& childNodesStorage)
{
    if (propertyValue.is_null())
    {
        struct RedfishPropertyLeafNull child{};
        childNodesStorage[propertyName] = child;
        bejTreeAddNull(root,
                       &std::get<struct RedfishPropertyLeafNull>(
                           childNodesStorage[propertyName]),
                       propertyName.c_str());
        return 0;
    }
    switch (property->format.principalDataType)
    {
        case bejNull:
        {
            struct RedfishPropertyLeafNull child{};
            childNodesStorage[propertyName] = child;
            bejTreeAddNull(root,
                           &std::get<struct RedfishPropertyLeafNull>(
                               childNodesStorage[propertyName]),
                           propertyName.c_str());
            break;
        }
        case bejInteger:
        {
            try
            {
                int64_t data = propertyValue.get<int64_t>();
                if (DEBUG)
                {
                    std::cerr << "Converted integer value: " << data
                              << std::endl;
                }
                struct RedfishPropertyLeafInt child{};
                childNodesStorage[propertyName] = child;
                bejTreeAddInteger(root,
                                  &std::get<struct RedfishPropertyLeafInt>(
                                      childNodesStorage[propertyName]),
                                  propertyName.c_str(), data);
            }
            catch (const json::exception& e)
            {
                std::cerr << "Integer Conversion error: " << e.what()
                          << std::endl;
                return -1;
            }
            break;
        }
        case bejEnum:
        {
            try
            {
                // Libbej APIs accept char* pointer for strings. So we need to
                // grab the json string value by reference as a local string
                // variable can get deallocated.
                std::string& data = propertyValue.get_ref<std::string&>();
                std::cerr << "Converted enum value: " << data << std::endl;
                struct RedfishPropertyLeafEnum child{};
                childNodesStorage[propertyName] = child;
                bejTreeAddEnum(root,
                               &std::get<struct RedfishPropertyLeafEnum>(
                                   childNodesStorage[propertyName]),
                               propertyName.c_str(), data.c_str());
            }
            catch (const json::exception& e)
            {
                std::cerr << "Enum Conversion error: " << e.what() << std::endl;
                return -1;
            }
            break;
        }
        case bejString:
        {
            try
            {
                // Libbej APIs accept char* pointer for strings. So we need to
                // grab the json string value by reference as a local string
                // variable can get deallocated
                std::string& data = propertyValue.get_ref<std::string&>();
                std::cerr << "Converted string value: " << data << std::endl;
                struct RedfishPropertyLeafString child{};
                childNodesStorage[propertyName] = child;
                bejTreeAddString(root,
                                 &std::get<struct RedfishPropertyLeafString>(
                                     childNodesStorage[propertyName]),
                                 propertyName.c_str(), data.c_str());
            }
            catch (const json::exception& e)
            {
                std::cerr << "String Conversion error: " << e.what()
                          << std::endl;
                return -1;
            }
            break;
        }
        case bejReal:
        {
            try
            {
                double data = propertyValue.get<double>();
                if (DEBUG)
                {
                    std::cerr << "Converted real/double value: " << data
                              << std::endl;
                }

                struct RedfishPropertyLeafReal child{};
                childNodesStorage[propertyName] = child;
                bejTreeAddReal(root,
                               &std::get<struct RedfishPropertyLeafReal>(
                                   childNodesStorage[propertyName]),
                               propertyName.c_str(), data);
            }
            catch (const json::exception& e)
            {
                std::cerr << "Real/Double Conversion error: " << e.what()
                          << std::endl;
                return -1;
            }
            break;
        }
        case bejBoolean:
        {
            try
            {
                bool data = propertyValue.get<bool>();
                std::cerr << "Converted boolean value: " << data << std::endl;
                struct RedfishPropertyLeafBool child{};
                childNodesStorage[propertyName] = child;
                bejTreeAddBool(root,
                               &std::get<struct RedfishPropertyLeafBool>(
                                   childNodesStorage[propertyName]),
                               propertyName.c_str(), data);
            }
            catch (const json::exception& e)
            {
                std::cerr << "Boolean Conversion error: " << e.what()
                          << std::endl;
                return -1;
            }
            break;
        }
        default:
            std::cerr << "Unknown Bej Data type " << std::endl;
            return -1;
    }
    return 0;
}

static int addBranchToBejTree(
    const uint8_t* schemaDict, uint16_t startingPropertyOffset,
    const std::string& propertyName, json& propertyValue,
    struct RedfishPropertyParent* root,
    std::unordered_map<std::string, BejChildNodesVariant>& childNodesStorage)
{
    uint16_t currentOffset;
    const struct BejDictionaryProperty* property = nullptr;

    // Get the property details from the schema dictionary to identify the
    // property type
    int rc = bejDictGetPropertyByName(schemaDict, startingPropertyOffset,
                                      propertyName.c_str(), &property,
                                      &currentOffset);
    if (rc != 0)
    {
        std::cerr << "Failed to find dictionary sequence for property "
                  << propertyName << " for the resource, rc : " << rc
                  << std::endl;
        return rc;
    }
    uint16_t childPointerOffset = property->childPointerOffset;

    if (property->format.principalDataType == bejPropertyAnnotation)
    {
        // As per Redfish specifiction, patching is not allowed on the Odata
        // annotation properties. So return error in this case.
        std::cerr
            << "It is an annotation property. Patching is not allowed on annotated properties"
            << std::endl;
        return -1;
    }
    else if (property->format.principalDataType == bejSet)
    {
        // If it is a set then link it with the parent and continue encoding the
        // rest of the BEJ tree

        struct RedfishPropertyParent child{};
        childNodesStorage[propertyName] = child;
        bejTreeInitSet(&std::get<struct RedfishPropertyParent>(
                           childNodesStorage[propertyName]),
                       propertyName.c_str());

        // Since it is a set, link the child to the parent and continue
        // recursively fetching the leaf property
        bejTreeLinkChildToParent(root, &std::get<struct RedfishPropertyParent>(
                                           childNodesStorage[propertyName]));

        // Iterate through the JSON object.
        // There could be multiple properties that are being patched at a time
        // and they can be present on different branches of the BEJ tree. So
        // construct the BEJ tree branches at each level
        for (const auto& it : propertyValue.items())
        {
            const std::string& childMemberPropertyName = it.key();
            if (DEBUG)
            {
                std::cerr << "Property name: " << childMemberPropertyName
                          << std::endl;
            }

            json& childMemberPropertyValue = it.value();

            rc = addBranchToBejTree(schemaDict, childPointerOffset,
                                    childMemberPropertyName,
                                    childMemberPropertyValue,
                                    &std::get<struct RedfishPropertyParent>(
                                        childNodesStorage[propertyName]),
                                    childNodesStorage);
            if (rc != 0)
            {
                return rc;
            }
        }
    }
    else
    {
        // If it is a leaf property then this is a property that has to be
        // updated/patched. The recursion ends when we find a leaf property
        rc = addLeafToBejTree(property, propertyName, propertyValue, root,
                              childNodesStorage);
        if (rc != 0)
        {
            return rc;
        }
    }

    return 0;
}

int encodePayloadForUpdateOp(const std::string& redfishReqPayload,
                             uint8_t** schemaDict, uint8_t** annotationDict,
                             std::vector<uint8_t>& encodedPayload)
{
    if (redfishReqPayload.empty())
    {
        return -1;
    }

    if ((schemaDict == nullptr) || (*schemaDict == nullptr))
    {
        std::cerr << "Schema dictionary cannot be NULL" << std::endl;
        return -1;
    }

    if ((annotationDict == nullptr) || (*annotationDict == nullptr))
    {
        std::cerr << "Annotation dictionary cannot be NULL" << std::endl;
        return -1;
    }

    BejDictionaries bejDictionaries;
    bejDictionaries.schemaDictionary = *schemaDict;
    bejDictionaries.annotationDictionary = *annotationDict;
    bejDictionaries.errorDictionary = nullptr;
    int rc;

    struct RedfishPropertyParent parent;
    bejTreeInitSet(&parent, nullptr);
    json redfishReqJsonPayload;

    // Get the Patch Data in JSON format
    try
    {
        redfishReqJsonPayload = json::parse(redfishReqPayload);
    }
    catch (const json::parse_error& e)
    {
        std::cerr << "JSON parsing error: " << e.what()
                  << " while parsing sensor collection response "
                  << redfishReqPayload << std::endl;
        return -1;
    }

    uint16_t rootOffset = bejDictGetPropertyHeadOffset();

    // Create a storage for the bej child nodes so that their memory is not
    // deallocated by the time we use the libbej encoder to encode the tree in
    // to a binary.
    std::unordered_map<std::string, BejChildNodesVariant> childNodesStorage;

    // Iterate through the JSON object
    // There could be multiple properties that are being patched at a time
    // and they can be present on different branches of the BEJ tree. So
    // construct the BEJ tree branches at each level
    for (const auto& it : redfishReqJsonPayload.items())
    {
        const std::string& memberPropertyName = it.key();
        if (DEBUG)
        {
            std::cerr << "Property name: " << memberPropertyName << std::endl;
        }
        json& memberPropertyValue = it.value();

        // Create a BEJ tree for encoding
        rc = addBranchToBejTree(bejDictionaries.schemaDictionary, rootOffset,
                                memberPropertyName, memberPropertyValue,
                                &parent, childNodesStorage);
        if (rc != 0)
        {
            return rc;
        }
    }

    libbej::BejEncoderJson encoder;
    rc = encoder.encode(&bejDictionaries, bejMajorSchemaClass, &parent);
    if (rc != 0)
    {
        std::cerr << "Encoding failure with rc: " << rc << std::endl;
        return rc;
    }
    encodedPayload = encoder.getOutput();
    return 0;
}

int encodePayloadForActionOp(const std::string& redfishReqPayload,
                             const std::string& action, uint16_t offset,
                             uint8_t** schemaDict, uint8_t** annotationDict,
                             std::vector<uint8_t>& encodedPayload)
{
    if (redfishReqPayload.empty())
    {
        return 0;
    }

    if ((schemaDict == nullptr) || (*schemaDict == nullptr))
    {
        std::cerr << "Schema dictionary cannot be NULL" << std::endl;
        return -1;
    }

    if ((annotationDict == nullptr) || (*annotationDict == nullptr))
    {
        std::cerr << "Annotation dictionary cannot be NULL" << std::endl;
        return -1;
    }

    BejDictionaries bejDictionaries;
    bejDictionaries.schemaDictionary = *schemaDict;
    bejDictionaries.annotationDictionary = *annotationDict;
    bejDictionaries.errorDictionary = nullptr;
    int rc;

    // Extract the action name (last component of action path, prepended with
    // '#')
    std::string actionName = action;
    size_t lastSlash = actionName.rfind('/');
    if (lastSlash != std::string::npos)
    {
        actionName = actionName.substr(lastSlash + 1);
    }
    if (actionName != "Oem" && actionName != "Actions")
    {
        if (actionName.empty() || actionName[0] != '#')
        {
            actionName = "#" + actionName;
        }
    }

    struct RedfishPropertyParent parent;
    bejTreeInitSet(&parent, actionName.c_str());

    json redfishReqJsonPayload;
    try
    {
        redfishReqJsonPayload = json::parse(redfishReqPayload);
    }
    catch (const json::parse_error& e)
    {
        std::cerr << "JSON parsing error: " << e.what()
                  << " while parsing Action request payload "
                  << redfishReqPayload << std::endl;
        return -1;
    }

    // Get the child pointer offset of the Action property using the passed
    // offset
    const struct BejDictionaryProperty* actionProperty =
        reinterpret_cast<const struct BejDictionaryProperty*>(*schemaDict +
                                                              offset);
    uint16_t startingPropertyOffset = actionProperty->childPointerOffset;

    std::unordered_map<std::string, BejChildNodesVariant> childNodesStorage;

    // Iterate through the JSON object and build the BEJ tree
    for (const auto& it : redfishReqJsonPayload.items())
    {
        const std::string& memberPropertyName = it.key();
        if (DEBUG)
        {
            std::cerr << "Property name: " << memberPropertyName << std::endl;
        }
        json& memberPropertyValue = it.value();

        rc = addBranchToBejTree(bejDictionaries.schemaDictionary,
                                startingPropertyOffset, memberPropertyName,
                                memberPropertyValue, &parent,
                                childNodesStorage);
        if (rc != 0)
        {
            return rc;
        }
    }

    libbej::BejEncoderJson encoder;
    rc = encoder.encode(&bejDictionaries, bejMajorSchemaClass, &parent, offset);
    if (rc != 0)
    {
        std::cerr << "Encoding failure with rc: " << rc << std::endl;
        return rc;
    }
    encodedPayload = encoder.getOutput();
    return 0;
}
