//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// JsonSerializer.cpp: Implementation of a JSON based serializer
// Note that for binary blob data only a checksum is stored so that
// a lossless  deserialization is not supported.

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "JsonSerializer.h"

#include "common/debug.h"

#include <anglebase/sha1.h>
#include <rapidjson/document.h>
#include <rapidjson/filewritestream.h>
#include <rapidjson/ostreamwrapper.h>
#include <rapidjson/prettywriter.h>

namespace angle
{

namespace js = rapidjson;

JsonSerializer::JsonSerializer() : mDoc(js::kObjectType), mAllocator(mDoc.GetAllocator()) {}

JsonSerializer::~JsonSerializer() {}

void JsonSerializer::startGroup(const std::string &name)
{
    mGroupValueStack.push(SortedValueGroup());
    mGroupNameStack.push(name);
}

void JsonSerializer::endGroup()
{
    ASSERT(!mGroupValueStack.empty());
    ASSERT(!mGroupNameStack.empty());

    rapidjson::Value group = makeValueGroup(mGroupValueStack.top());
    std::string name       = mGroupNameStack.top();

    mGroupValueStack.pop();
    mGroupNameStack.pop();

    addValue(name, std::move(group));
}

void JsonSerializer::addBlob(const std::string &name, angle::Span<const uint8_t> blob)
{
    addBlobWithMax(name, blob, 16);
}

void JsonSerializer::addBlobWithMax(const std::string &name,
                                    angle::Span<const uint8_t> blob,
                                    size_t maxSerializedLength)
{
    unsigned char hash[angle::base::kSHA1Length];
    angle::base::SHA1HashBytes(blob.data(), blob.size(), hash);
    std::ostringstream os;

    // Since we don't want to de-serialize the data we just store a checksum of the blob
    os << "SHA1:";
    static constexpr char kASCII[] = "0123456789ABCDEF";
    for (size_t i = 0; i < angle::base::kSHA1Length; ++i)
    {
        os << kASCII[hash[i] & 0xf] << kASCII[hash[i] >> 4];
    }

    std::ostringstream hashName;
    hashName << name << "-hash";
    addString(hashName.str(), os.str());

    if (blob.size() > maxSerializedLength)
    {
        blob = blob.first(maxSerializedLength);
    }
    std::vector<uint8_t> data(blob.begin(), blob.end());
    std::ostringstream rawName;
    rawName << name << "-raw[0-" << data.size() - 1 << ']';
    addVector(rawName.str(), data);
}

void JsonSerializer::addCString(const std::string &name, const char *value)
{
    rapidjson::Value val(value, mAllocator);
    addValue(name, std::move(val));
}

void JsonSerializer::addString(const std::string &name, const std::string &value)
{
    addCString(name, value.c_str());
}

void JsonSerializer::addVectorOfStrings(const std::string &name,
                                        const std::vector<std::string> &value)
{
    rapidjson::Value arrayValue(rapidjson::kArrayType);
    arrayValue.SetArray();

    for (const std::string &v : value)
    {
        rapidjson::Value str(v.c_str(), mAllocator);
        arrayValue.PushBack(str, mAllocator);
    }

    addValue(name, std::move(arrayValue));
}

void JsonSerializer::addBool(const std::string &name, bool value)
{
    rapidjson::Value boolValue(value);
    addValue(name, std::move(boolValue));
}

void JsonSerializer::addHexValue(const std::string &name, int value)
{
    // JSON doesn't support hex values, so write it as a string
    std::stringstream hexStream;
    hexStream << "0x" << std::uppercase << std::setfill('0') << std::setw(4) << std::hex << value;
    addCString(name, hexStream.str().c_str());
}

const char *JsonSerializer::data()
{
    ensureEndDocument();
    return mResult.c_str();
}

std::vector<uint8_t> JsonSerializer::getData()
{
    ensureEndDocument();
    return std::vector<uint8_t>(mResult.begin(), mResult.end());
}

void JsonSerializer::ensureEndDocument()
{
    if (!mResult.empty())
    {
        return;
    }

    std::stringstream os;
    js::OStreamWrapper osw(os);
    js::PrettyWriter<js::OStreamWrapper> prettyOs(osw);
    mDoc.Accept(prettyOs);
    mResult = os.str();
}

size_t JsonSerializer::length()
{
    ensureEndDocument();
    return mResult.length();
}

rapidjson::Value JsonSerializer::makeValueGroup(SortedValueGroup &group)
{
    rapidjson::Value valueGroup(js::kObjectType);
    for (auto &it : group)
    {
        rapidjson::Value tag(it.first.c_str(), mAllocator);
        valueGroup.AddMember(tag, it.second, mAllocator);
    }
    return valueGroup;
}

void JsonSerializer::addValue(const std::string &name, rapidjson::Value &&value)
{
    if (!mGroupValueStack.empty())
    {
        mGroupValueStack.top().insert(std::make_pair(name, std::move(value)));
    }
    else
    {
        rapidjson::Value nameValue(name, mAllocator);
        mDoc.AddMember(nameValue, std::move(value), mAllocator);
    }
}
}  // namespace angle
