/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2013-2017 Nest Labs, 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 "lib/support/CHIPMemString.h"
#include "lib/support/ScopedBuffer.h"
#include <lib/core/DataModelTypes.h>
#include <lib/support/Base64.h>
#include <lib/support/jsontlv/TlvJson.h>

namespace {
/*
 * Encapsulates the different types of keys permissible.
 *
 * Root Key = Key with a name of 'value'. This is the top-most key in a given JSON object generated from TLV.
 * Struct Field = Key containing the 32-bit field ID of an item in a struct.
 * Array Item = Key containing the 16-bit list index of an item in a list.
 *
 * In the latter two modes, the actual field ID/list index is encapsulated within the 'key' member.
 *
 */
struct KeyContext
{
    enum KeyType
    {
        kRoot,
        kStructField,
        kArrayItem
    };

    KeyContext() = default;

    KeyContext(chip::FieldId fieldId)
    {
        keyType = kStructField;
        key     = fieldId;
    }

    KeyContext(chip::ListIndex listIndex)
    {
        keyType = kArrayItem;
        key     = listIndex;
    }

    KeyType keyType  = kRoot;
    unsigned int key = 0;
};
} // namespace

//
// For now, let's put a bound of the maximum length of a byte/char string to be the size of an IPv6
// MTU. While this is smaller than that of the limit defined in the data model specification,
// strings by virtue of not being chunked are intrinsically limited in size to the size of the encompassing packet.
//
static constexpr uint16_t kMaxStringLen = 1280;

namespace chip {

/*
 * This templated function inserts a key/value pair into the Json value object.
 * The value is templated to be of type T and accepts any of the following primitive
 * types:
 *      bool, uint*_t, int*_t, char *, float, double.
 *
 * This method uses the provided key context to deduce the type of element being added.
 *
 */
template <typename T>
void InsertKeyValue(Json::Value & json, const KeyContext & keyContext, T val)
{
    //
    // This needs to accomodate either the string 'value', or a 32-bit integer.
    // The size of the largest 32-bit integer key represented as a string is 11 characters long.
    // Tack on 1 byte for the null character.
    //
    char keyBuf[12];

    if (keyContext.keyType == KeyContext::kRoot)
    {
        Platform::CopyString(keyBuf, sizeof(keyBuf), "value");
        json[keyBuf] = val;
    }
    else if (keyContext.keyType == KeyContext::kStructField)
    {
        snprintf(keyBuf, sizeof(keyBuf), "%u", keyContext.key);
        json[keyBuf] = val;
    }
    else
    {
        json[keyContext.key] = val;
    }
}

std::string JsonToString(Json::Value & json)
{
    Json::FastWriter writer;
    writer.omitEndingLineFeed();
    return writer.write(json);
}

CHIP_ERROR TlvToJson(TLV::TLVReader & reader, KeyContext context, Json::Value & parent)
{
    bool isStruct = false;

    switch (reader.GetType())
    {
    case TLV::kTLVType_UnsignedInteger: {
        uint64_t v;
        ReturnErrorOnFailure(reader.Get(v));
        InsertKeyValue(parent, context, v);
        break;
    }

    case TLV::kTLVType_SignedInteger: {
        int64_t v;
        ReturnErrorOnFailure(reader.Get(v));
        InsertKeyValue(parent, context, v);
        break;
    }

    case TLV::kTLVType_Boolean: {
        bool v;
        ReturnErrorOnFailure(reader.Get(v));
        InsertKeyValue(parent, context, v);
        break;
    }

    case TLV::kTLVType_FloatingPointNumber: {
        double v;
        ReturnErrorOnFailure(reader.Get(v));
        InsertKeyValue(parent, context, v);
        break;
    }

    case TLV::kTLVType_ByteString: {
        ByteSpan span;

        ReturnErrorOnFailure(reader.Get(span));
        VerifyOrReturnError(span.size() < kMaxStringLen, CHIP_ERROR_INVALID_TLV_ELEMENT);

        Platform::ScopedMemoryBuffer<char> byteString;
        byteString.Alloc(BASE64_ENCODED_LEN(span.size()) + 1);
        VerifyOrReturnError(byteString.Get() != nullptr, CHIP_ERROR_NO_MEMORY);

        auto encodedLen              = Base64Encode(span.data(), span.size(), byteString.Get());
        byteString.Get()[encodedLen] = '\0';

        InsertKeyValue(parent, context, byteString.Get());
        break;
    }

    case TLV::kTLVType_UTF8String: {
        CharSpan span;

        ReturnErrorOnFailure(reader.Get(span));
        VerifyOrReturnError(span.size() < kMaxStringLen, CHIP_ERROR_INVALID_TLV_ELEMENT);

        Platform::ScopedMemoryString charString(span.data(), span.size());
        InsertKeyValue(parent, context, charString.Get());
        break;
    }

    case TLV::kTLVType_Null: {
        InsertKeyValue(parent, context, Json::Value());
        break;
    }

    case TLV::kTLVType_Structure:
        isStruct = true;

        //
        // Fall-through to the case below since
        // arrays and structs are handled similarly with
        // just a small difference in terms of handling of field IDs vs.
        // list indices of the elements in the respective collections.
        //

    case TLV::kTLVType_Array: {
        TLV::TLVType containerType;

        ReturnErrorOnFailure(reader.EnterContainer(containerType));

        CHIP_ERROR err;
        Json::Value value;
        size_t listIndex = 0;

        while ((err = reader.Next()) == CHIP_NO_ERROR)
        {
            if (isStruct)
            {
                VerifyOrReturnError(TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG);
                KeyContext context2(static_cast<chip::FieldId>(TLV::TagNumFromTag(reader.GetTag())));

                //
                // Recursively convert to JSON the encompassing item within the struct.
                //
                ReturnErrorOnFailure(TlvToJson(reader, context2, value));
            }
            else
            {
                KeyContext context2(static_cast<chip::ListIndex>(listIndex++));

                //
                // Recursively convert to JSON the encompassing item within the array.
                //
                ReturnErrorOnFailure(TlvToJson(reader, context2, value));
            }
        }

        VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
        ReturnErrorOnFailure(reader.ExitContainer(containerType));
        InsertKeyValue(parent, context, value);
        break;
    }

    default:
        return CHIP_ERROR_INVALID_TLV_ELEMENT;
        break;
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR TlvToJson(TLV::TLVReader & reader, Json::Value & root)
{
    KeyContext context;
    return TlvToJson(reader, context, root);
}

} // namespace chip
