/*
 *
 *    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;

constexpr const char kBase64Header[] = "base64:";
constexpr size_t kBase64HeaderLen    = ArraySize(kBase64Header) - 1;

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)
{
    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(kBase64HeaderLen + BASE64_ENCODED_LEN(span.size()) + 1);
        VerifyOrReturnError(byteString.Get() != nullptr, CHIP_ERROR_NO_MEMORY);

        auto encodedLen = Base64Encode(span.data(), static_cast<uint16_t>(span.size()), byteString.Get() + kBase64HeaderLen);
        if (encodedLen)
        {
            memcpy(byteString.Get(), kBase64Header, kBase64HeaderLen);
            encodedLen = static_cast<uint16_t>(encodedLen + kBase64HeaderLen);
        }
        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: {
        TLV::TLVType containerType;
        ReturnErrorOnFailure(reader.EnterContainer(containerType));

        CHIP_ERROR err;
        Json::Value value;

        while ((err = reader.Next()) == CHIP_NO_ERROR)
        {
            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));
        }

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

    case TLV::kTLVType_Array: {
        TLV::TLVType containerType;
        ReturnErrorOnFailure(reader.EnterContainer(containerType));

        CHIP_ERROR err;
        Json::Value value = Json::Value(Json::arrayValue);
        size_t listIndex  = 0;

        while ((err = reader.Next()) == CHIP_NO_ERROR)
        {
            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
